web-dev-qa-db-ja.com

ランタイムタイプで実行されるジェネリックメソッド

私は次のコードを持っています:

 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()を実行できないことがわかりました。この関数を使用する他の方法はありますか?

29
Sarit

できますが、それは反省を伴いますが、あなたはそれを行うことができます。

typeof(ClassExample)
    .GetMethod("DoSomething")
    .MakeGenericMethod(p.DisplayType)
    .Invoke(this, new object[] { p.Name, p.Value });

これにより、含まれているクラスの先頭が表示され、メソッド情報が取得され、適切なタイプのジェネリックメソッドが作成されます。その後、Invokeを呼び出すことができます。

36
Chris Patterson
this.GetType().GetMethod("DoSomething").MakeGenericMethod(p.Value.GetType()).Invoke(this, new object[]{p.Name, p.Value});

動作するはずです。

5

ジェネリック型は、実行時にここで希望する方法で指定することはできません。

最も簡単なオプションは、DoSomethingの非ジェネリックオーバーロードを追加するか、単にDoSomething<object>を呼び出してp.DisplayTypeを無視することです。 SendToDatabasevalueの-​​コンパイル時タイプに依存しない限り(おそらくそうではないはずです)、object

それができない場合は、リフレクションを使用してDoSomethingを呼び出す必要があり、パフォーマンスに大きな打撃を与えます。

3
SLaks

まず、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 });
3
stevemegson

これには MethodInfo.MakeGenericMethod を使用できると厳密に言っています。

ただし、DoSomethingを非汎用形式に変更することをお勧めします。これは、それが本当に汎用である必要があるかどうかが明確でないためです。

1
elder_george