2016-05-18 14 views
1

オブジェクトをインスタンス化するときに渡された型と同じ型を使用するジェネリックメソッドを持っています。実行時に、私はそのオブジェクト名の文字列表現で渡す必要のあるオブジェクトの名前しか知りません。私はActivatorを使用し、おそらく動的を使用することについていくつかのことを読んだことがありますが、私はこの作業をどのように行う必要があるかについて私の頭を覆すことはできません。ジェネリック型のクラスのインスタンスを作成し、実行時にオブジェクトの文字列名から同じジェネリック型のメソッドを呼び出す

public class MyClass<T> where T : class, new() 
{ 
     public IList<T> MyMethod(Stream stream) 
     { 
      var data = new List<T>(); 
      // stuff to create my list of objects 
      return data; 
     } 
} 

私は、文字列として渡しているオブジェクトの名前に基づいてMyMethodは()メソッドから、私のIListを返す必要があります。ここに私のジェネリッククラスがどのように見えるかの抜粋です。

私はちょうど文字列のスイッチ/ケースを行い、 "本当の"オブジェクトへの参照でケース内のMyClassをインスタンス化することができますが、より良い(より短く、よりクリーンな)方法があれば疑問に思っていますこの。

public class MyClass<T> where T : class, new() 

それは基本的に "Tがクラスで、デフォルトのコンストラクタを持つ必要がある" と言う:

TIA

+0

あなたはアイテムのタイプが 'T'であるが、タイプは文字列から来ていると言っているように聞こえるかもしれません。 –

+0

私は、クラスの名前を文字列として渡すことによってジェネリック型をインスタンス化したいと思っています。その文字列から汎用のIList <>を宣言したいのですが正しい? – entropic

+0

これはまさに正しいことです。モデル名(T)をデータベースの文字列値から取得する予定です。だから私はMyClassオブジェクトを作成し、モデルの文字列表現から生成しなければならないTを渡すことで、MyMethodメソッドを自分のオブジェクトのインスタンス上で呼び出すことができる必要があります。 jgauffinの答えをより明確にするためのコメントを見てください。 –

答えて

3

はあなたのラッパーは、以下の署名を得ました。興味深い部分は、デフォルトコンストラクタに関するものです。つまり、クラスには引数のないコンストラクタが必要です。

それはあなたが呼び出すことができます.NETを伝えます:

var obj = new T(); 

だから、最初のステップは、まさにそれを行うことです。

public class MyClass<T> where T : class, new() 
{ 
     public IList<T> MyMethod(Stream stream) 
     { 
      var data = new List<T>(); 

      //this 
      var obj = new T(); 

      return data; 
     } 
} 

あなたがメソッドを呼び出すために望んでいた隣。それはreflectionの助けを借りて行われます。

簡単な例は次のとおりです。基づいて、私は(MyMethodはからの私のIListを返す必要が

)方法:私は重要な部分を逃し

var obj = new T(); 

//get type information 
var type = obj.GetType(); 

//find a public method named "DoStuff" 
var method = type.GetMethod("DoStuff"); 

// It got one argument which is a string. 
// .. so invoke instance **obj** with a string argument 
method.Invoke(obj, new object[]{"a string argument"}); 

更新文字列として渡すオブジェクトの名前。

タイプはあなただけSome.Namespace.ClassName" to Type.GetType() `のような完全なタイプ名を渡すことができ、あなたの実行コードと同じアセンブリ内で宣言されている場合:クラスが別で宣言されている場合

var type = Type.GetType("Some.Namespace.ClassName"); 
var obj = Activator.CreateInstance(type); 

アセンブリを指定する必要があります:

var type = Type.GetType("Some.Namespace.ClassName, SomeAsseblyName"); 
var obj = Activator.CreateInstance(type); 

残りはほぼ同じです。

あなただけが正しい種類を見つけるために、アセンブリを通過することができ、クラス名がある場合:

var type = Assembly.GetExecutingAssembly() 
        .GetTypes() 
        .FirstOrDefault(x => x.Name == "YourName"); 
var obj = Activator.CreateInstance(type); 
+0

私は十分に私の問題を説明していないと思います。モデルタイプをハードコードするときに必要なものを返すメソッドがあります:var myObject = new MyClass ();その後、IList のデータ= myObject.MyMethod(someStream);私が必要とするのは、このモデルをどのようなモデルタイプに対してもダイナミックにできることです。 IEでは、実行時までモデルの型(上記のMyModel)を知ることはできません。その時点では、モデルの名前だけを文字列として認識します。だから私は "MyModel"や "MyModel2"などを持つことができ、MyClassのインスタンスを作成する必要があります。ここで私はTを文字列としてしか知りません。 –

+0

jgauffinの更新をありがとう。私は今これを試みている:var cs = new MyClass (); objはActivator.CreateInstance(type)から設定されていて、VSは私に吠えています。私はオブジェクトのインスタンスではなく、 "型"を渡す必要があるためだと思います。 –

+0

コンパイル時にどのようなオブジェクトであるかわからない場合は型制約( 'T')を使用できません。代わりに 'object'のリストに変更してください。 – jgauffin

0

使用リフレクションを。 MyMethodを静的にします。以下のコードを参照してください:

public object run(string typename, Stream stream) 
{ 
     var ttype = Assembly 
      .GetExecutingAssembly() 
      .GetTypes() 
      .FirstOrDefault(x => x.Name == typename); 
     MethodInfo minfo = typeof(MyClass) 
      .GetMethod("MyMethod", BindingFlags.Static | BindingFlags.Public); 
     return minfo 
      .MakeGenericMethod(ttype) 
      .Invoke(null, new object[] { stream }); 
} 
1

ジェネリック型を作成してインスタンスを作成できるように思えます。

//Assuming "typeName" is a string defining the generic parameter for the 
//type you want to create. 
var genericTypeArgument = Type.GetType(typeName); 
var genericType = typeof (MyGenericType<>).MakeGenericType(genericTypeArgument); 
var instance = Activator.CreateInstance(genericType); 

これは、すでにそのジェネリック型ための型引数ジェネリック型が何であるかを知っているが、ないことを前提としています。つまり、<T>が何であるかを判断しようとしています。

+0

私にそれを打つ - しかし、これは私の正確な答えになるだろう。 – entropic

関連する問題