2012-01-24 16 views
0

ジェネリックファクトリを返すクラスがコンストラクタ内のパラメータを必要とするときに、それを実現する方法はありますか?すべての私の工場は次のようになります。私のように何のパラメータなしのコンストラクタを持たないクラスを使用することはできませんのでActivator.CreateInstance()を使用して、パラメータを持つコンストラクタを持つジェネリックファクトリを作成することはできますか?

public static TServiceClass GetService<TServiceClass>() 
     where TServiceClass : class, new() 
    { 
     TServiceClass serviceClass = null; 

     string repositoryName = typeof (TServiceClass).ToString().Replace("Service", "Repository"); 
     Type type = Type.GetType(repositoryName); 

     if (type != null) 
     { 
      object repository = Activator.CreateInstance(type); 
      serviceClass = (TServiceClass)Activator.CreateInstance(typeof (TServiceClass), new[]{repository}); 
     } 

     return serviceClass; 
    } 

しかし、これはもちろん動作しません。

public static class UserServiceFactory 
{ 
    public static UserService GetService() 
    { 
     UserRepository userRepository = new UserRepository(); 
     return new UserService(userRepository); 
    } 

} 

私はこのような何かを試してみました一般的なパラメータですが、私は近くにいるように感じます。私はGetService(Type serviceClassType)のようなServiceクラスを渡すことを考えましたが、メソッドの戻り値の型を宣言することはできず、呼び出したいときにキャストする必要がありました。

別の方法がありますか?これも可能ですか?

+0

@vcsjonesどういう意味ですか?通常は私の工場を使ってDIingを行います(サービスがリポジトリを必要とし、私の工場がそれを処理しているのが分かるように)。サービスごとに具体的な実装が必要ではないでしょうか?また、担当者の回答セクションに投稿してください! – SventoryMang

+0

申し訳ありませんが、私は誤解しました。 – vcsjones

+0

@vcsjonesあなたは正しいですが、new()は削除されました。だから回答セクションに投稿してください! – SventoryMang

答えて

3

あなたはこのような何かをし、型パラメータとして両方のタイプを取ることができる:

public static TService GetService<TRepository, TService>() where TRepository:new() 
{ 
    var repository = new TRepository(); 
    return (TService)Activator.CreateInstance(typeof(TService), repository); 
} 

それとも、あなたはサービスとリポジトリは、(単に説明のために)同じ名前であることを慣例に頼るしたい場合:

public static TService GetService<TService>() 
{ 
    var repositoryName = String.Concat(typeof(TService).Namespace, Type.Delimiter, typeof(TService).Name.Replace("Service", "Repository")); 
    object repository = Activator.CreateInstance(Type.GetType(repositoryName)); 
    return (TService)Activator.CreateInstance(typeof(TService), repository); 
} 

これは明らかではなく、直感的ではなく、おそらくより優れた、より堅牢なソリューションがあります。

おそらくinversion of control containerを使用する方が適切なアプローチになります。

コンテナを使用して、ちょうどUserServiceを解決し、コンテナに適切なリポジトリを注入させます。 UserServiceが他のものからの依存関係である場合、DIコンテナがそれを解決するようにし、最新のコンテナは依存関係の依存関係を解決します。

+0

ありがとう、私は最初の方法を考えましたが、コンベンションは常にそこにあり、できるだけシンプルなメソッド呼び出しを保ちたいと思いました。あなたのDIコンテナのコメントについてはまだ混乱していますが、現在の工場はあなたのリンクにあるような依存性注入を既に使用していますか?あなたは擬似コードでも役立つでしょうか、簡単な例ができますか? – SventoryMang

関連する問題