私は次のコードを持っています:
public class ClassExample
{
void DoSomthing<T>(string name, T value)
{
SendToDatabase(name, value);
}
public class ParameterType
{
public readonly string Name;
public readonly Type DisplayType;
public readonly string Value;
public ParameterType(string name, Type type, string value)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("name");
if (type == null)
throw new ArgumentNullException("type");
this.Name = name;
this.DisplayType = type;
this.Value = value;
}
}
public void GetTypes()
{
List<ParameterType> l = report.GetParameterTypes();
foreach (ParameterType p in l)
{
DoSomthing<p.DisplayType>(p.Name, (p.DisplayType)p.Value);
}
}
}
DoSomething()を実行できないことがわかりました。この関数を使用する他の方法はありますか?
できますが、それは反省を伴いますが、あなたはそれを行うことができます。
typeof(ClassExample)
.GetMethod("DoSomething")
.MakeGenericMethod(p.DisplayType)
.Invoke(this, new object[] { p.Name, p.Value });
これにより、含まれているクラスの先頭が表示され、メソッド情報が取得され、適切なタイプのジェネリックメソッドが作成されます。その後、Invokeを呼び出すことができます。
this.GetType().GetMethod("DoSomething").MakeGenericMethod(p.Value.GetType()).Invoke(this, new object[]{p.Name, p.Value});
動作するはずです。
ジェネリック型は、実行時にここで希望する方法で指定することはできません。
最も簡単なオプションは、DoSomething
の非ジェネリックオーバーロードを追加するか、単にDoSomething<object>
を呼び出してp.DisplayType
を無視することです。 SendToDatabase
がvalue
の-コンパイル時タイプに依存しない限り(おそらくそうではないはずです)、object
。
それができない場合は、リフレクションを使用してDoSomething
を呼び出す必要があり、パフォーマンスに大きな打撃を与えます。
まず、p.Value
を正しい型に変換する必要があります。これは、コンパイル時に型がわかっていても、文字列をメソッドに直接渡すことができないためです。
DoSomething<Int32>( "10" ); // Build error
単純な数値タイプとDateTimeの場合、次を使用できます
object convertedValue = Convert.ChangeType(p.Value, p.DisplayType);
これで、リフレクションを使用して、必要なジェネリックメソッドを呼び出すことができます...
typeof(ClassExample)
.GetMethod("DoSomething")
.MakeGenericMethod(p.DisplayType)
.Invoke(this, new object[] { p.Name, convertedValue });
これには MethodInfo.MakeGenericMethod を使用できると厳密に言っています。
ただし、DoSomethingを非汎用形式に変更することをお勧めします。これは、それが本当に汎用である必要があるかどうかが明確でないためです。