2011-10-27 15 views
4

これが可能かどうかわかりませんし、実装ごとに拡張メソッドを記述する必要があるかもしれません。いくつかのコード例を示します:インタフェースの正しい実装を返す拡張メソッド?

public interface IBaseService<T> 
{ 
    IUnitOfwork UnitOfWork {get;} 
} 

public interface IService<T>: IBaseService<T> 
{ 
    IEnumerable<T> GetAll(); 
    T GetById(Guid id); 
} 

public interface IUserService: IService<User> 
{ 
    User FindByUsernameAndPassword(string username, string password) 
} 

public class BaseService<T>: IService<T> 
{ 

    public BaseService(IRepository<T> repository) 
    { 
     _repository = repository 
    } 
    public virtual IEnumerable<T> GetAll(){....}; 
    public virtual T GetById(Guid id){....}; 
    IUnitOfWork UnitOfWork {get {return _repository.UnitOfWork;}} 
} 

public class UserService: BaseService<User>, IUserService 
{ 
    ... 
} 

public static class ServiceExtensions 
{ 
    public static IBaseService<T> EnableLazyLoading<T>(this IBaseService<T> service, bool lazyLoad = True) 
    { 
      service.UnitOfWork.EnableLazyLoad(lazyLoad); 
      return service; 
    } 
} 

だから、私はUserServiceを使っています。私はUserServiceの上の拡張メソッドを呼び出すと、それはそれはIBaseServiceの適切な実装を返すか、私はそれぞれの実装のために作成し、拡張メソッドをする必要がありますすることが可能です?:

例:

userService.EnableLazyLoading(false).FindByUsernameAndPassword("ddivita","123456") 
+0

それで、明確にするために、それが呼び出されたものは何でも新しいバージョンを作成したいと言っていますか? –

+0

私は、IBaseServcie のすべての実装で使用される1つの拡張メソッドを書いて、正しい実装を返すことを望みます。私の例では、EnableLazyLoading拡張を呼び出すときにIUserServiceを返す方法を理解したいと思います。 – DDiVita

+0

ああ!私は、それが呼び出された特定の型を返すようにしたいので、その新しいインスタンスを作成しません。 –

答えて

3

ますそれをこのように行うことができます。

public static S EnableLazyLoading<T, S>(this S service, bool lazyLoad = true) 
    where S : IBaseService<T> 
{ 
    service.UnitOfWork.EnableLazyLoad(lazyLoad); 
    return service; 
} 
+0

私は同じ答えを考え出しました。タイプ(OPで大丈夫かもしれません)を推論することはできないので、明示的に呼び出す必要があります: 'userService.EnableLazyLoading (false)... ' –

+0

はい、それは当てはまりますが、拡張メソッドをn回作成するよりもこの方法が好きです。拡張メソッドが複数ある場合は、インターフェイスから抽象クラスに変更するだけです。 –

+0

ああ、私は全く同意します。ちょうど不利な点を指摘する。 –

2

大丈夫、これは、またはあなたのデザインでは動作しない場合がありますが、それはフェリックスの回答に基づいています(彼はのためにクレジットを取得する必要がある)、それは推測可能なことができます。

あなたUnitOfWorkクラスがタイプTに依存しないので、あなたはIBaseService<T>がそうのようなIBaseServiceを延長させる、その後、UnitOfWorkメンバーが含まれている非汎用的であるIBaseServiceを作成することができますの残りの部分を維持し、その後

public interface IBaseService 
{ 
    // all non-type-T related stuff 
    IUnitOfwork UnitOfWork {get;} 
} 

public interface IBaseService<T> : IBaseService 
{ 
    // .. all type T releated stuff 
} 

通常のようにクラス設計として拡張メソッドを記述します。私たちはGEへIBaseService<T>を必要としないので

public static S EnableLazyLoading<S>(this S service, bool lazyLoad = true) 
    where S : IBaseService 
{ 
    service.UnitOfWork.EnableLazyLoad(lazyLoad); 
    return service; 
} 

t UnitOfWork今、推論を問題にしていた第2の型パラメータTを指定する必要はありません。それが今Sを推測することができますので、あなたが望んでいたように、今、私たちは、正確にコードを書くことができますタイプTUser)について知っておく必要がなくUserServiceです:これは私が言ったように、想定していることは、もちろん

userService.EnableLazyLoading(false).FindByUsernameAndPassword("ddivita","123456"); 

UnitOfWorkにはタイプTのものは必要ありません。

私が言ったように、@ Felixは答えに値するが、それを推測できる方法を拡張して、ジェネリック型パラメータを渡す必要がないようにしたい。しかし、アップ投票は高く評価されています:-)

+0

ああ、それは素晴らしいです! – DDiVita

+0

@DDiVita:ありがとう、私はフェリックスが答えに値すると言いましたが、私は彼の仕事の上に構築していました。 –

+1

これは素晴らしい、btw働いた。私のUoWはタイピングされていないので、完璧な解決策でした。あなたとフェリックスのおかげで – DDiVita

関連する問題