2009-09-16 10 views
7

私はC#のジェネリックス機能を使用するファクトリメソッドを構築しようとしています。C#Generics - 型パラメータの制約

このファクトリメソッドでは、いくつかの特定のクラスに制約を加えたいと思います。これらのクラスには、すべてデフォルトのコンストラクタがありません。

これは私の例です。誰かがそれを実行することができるかどうか教えてもらえますか?

public class AbstractClass { 
    //this abstract class does not have a default constructor, nor its subclasses 
    public AbstractClass(SomeClassName obj) { 
     //use obj for initialization 
    } 
} 

//this factory class should create objects of type T that inherit 
//from AbstractClass and invoke the non-default constructor 
public class FactoryClass { 
    public static T BuildObject<T> (SomeClassName obj) where T: AbstractClass { 
     return new T(obj); //does not work?!?!?! 
    } 
} 


//Edit: ANSWER!!! 
public static T BuildObject<T>(SomeClassUsedForTheConstructor item) where T : SomeAbstractClass { 
return (T) Activator.CreateInstance(typeof (T), item); 
} 

答えて

4

TypeクラスとGetConstructorを見てください。 ConstructorInfoオブジェクトを取得したら、Invokeメソッドを使用します。

var x = typeof(T); 
var t = x.GetConstructor(new[] {obj.GetType()}); 
object u = t.Invoke(<inputs>); 
+0

これは私が使っていたものですが、今はBrianが述べたように 'Activator.CreateInstance'を使用しています。 –

3

いいえ、組み込みの一般的な制約を単独で使用することはできません。 新しいキーワードでは、ジェネリック型にデフォルトのコンストラクタを含めることのみを制限できます。

+0

T:new()が定義されている場合のみ。 –

4

制限タイプでa default constructorを指定しないで汎用タイプをインスタンス化することはできません。

代わりに、ファクトリクラスがSomeClassNameパラメータをIAbstractClassのプロパティとして設定できるように、インターフェイスIAbstractClassを指定することを検討してください。

また、AbstractClassを初期化するためにSomeClassNameインスタンスが必要な場合は、空のデフォルトコンストラクタがあるが、IAbstractClassで定義されたリッチイニシャライザメソッドもあると考えてください。たとえば:

public interface IAbstractClass { void Initialize(SomeClassName obj); } 

そうすれば、あなたの静的BuildObject方法が代わりに行います。

public static T BuildObject<T>(SomeClassName obj) where T: AbstractClass 
{ 
    T newObject = new T(); 
    IAbstractClass ac = newObject as IAbstractClass; 
    ac.Initialize(obj); 
} 
5

は、私はそれが本当にうまく機能型Tの新しいオブジェクトを作成する必要が私のジェネリック医薬品でActivator.CreateInstance(typeof(T))を使用したいです。

+0

これは.net rocksポッドキャストに入るはずです!答えに感謝します。 – Pablo

+0

//最終的なコード パブリック静的T BuildObject (SomeClassUsedForTheConstructorアイテム)T:SomeAbstractClass {リターン(T)Activator.CreateInstance(typeof演算(T)、項目); } – Pablo

+2

遅いですし、コンパイル時のチェックがありません... –

関連する問題