2009-09-03 4 views
8

この質問の要素は以前は聞いたことがありますが、回答を見つけるのが難しいです。 (免責事項:これは関連していますが、私が最近尋ねた質問とは別です)。汎用オブジェクトパラメータの実際のタイプを取得する

私はこのような方法があります:

public static void Method<T>(MethodInfo m, T value) 
{ 
    Type memberType = m.GetValueType(); 

    if (memberType.IsAssignableFrom(typeof(List<T>)) 
    { 
    object memberValue = Activator.CreateInstance(memberType); 
    ((List<T>)memberValue).Add(value); 
    } 
} 

これは、私がこのようにそれを呼び出したときに正常に動作します:しかし、私はジェネリック型を使用してこのメ​​ソッドを呼び出す必要が

string s = "blah"; 
Method(memberInfo, s); 

ので、私メソッド< Tの値 ':「このようにそれを呼び出すmは今

Type valueType = someType; 
object passValue = someMethod.MakeGenericMethod(new Type[] { valueType }).Invoke(this, new object[] { }); 
/* Call my original method */ 
Method(memberInfo, passValue); 

、インテリセンスは、知っている'> IどのタイプのvalueType(「FooObject」など)であってもかまいません。しかし、 'T'はオブジェクトです。つまり、リスト<FooObject>はではなく、リスト< T>(リスト<オブジェクト>)からを割り当てることができます。

私は変数( 'passValue')にConvert.ChangeTypeを使用しようとしましたが、これはもう役に立ちませんでした。

タイプ変数のタイプに変数をキャストする方法がないので、どうすればこの問題を回避できますか?

どうやらIsAssignableFromに頼らず、これが機能するかどうかのより緩やかな型チェックを行うのが最善の解決策ですか?この問題は、 'T'が本当にmemberValueの要素型でない限り、memberValueを適切にキャストできないことがわかりません。

+0

GetValueType()は、コード内の拡張メソッドです。しかし、コードを見ていなくても、メソッド 'Method 'は何もしません...何か?私はあなたに改善された解決策を提供したいと思いますが、ここで何をしようとしているのか分かりません。 –

+0

申し訳ありませんgetvaluetypeは、特定のMemberTypeに応じて特定のMemberInfoのFieldType/PropertyTypeを呼び出すメソッドです。メソッドは、リストを表すMemberInfoにオブジェクトを追加します(つまり、リストであるフィールドまたはプロパティ)。 –

答えて

4

あなたは幸運です。私は実際にはhad to do something very similar数週間前です。

詳細については上記のブログ記事を参照してください。基本的な考え方は型を反映し、明示的なパラメータセットでメソッドを手動で呼び出すことです。

typeof(MyClass).GetMethod("Foo").MakeGenericMethod(new[] { param.GetType() }).Invoke(null, new[] { param }); 

それは 非常に タイプセーフではありませんが、それはあなたが探しているまさにありません。

class Program 
{ 

    static void Main(string[] args) 
    { 
     object str = "Hello World"; 
     object num = 5; 
     object obj = new object(); 

     Console.WriteLine("var\tvalue\t\tFoo() Type\tCallFoo() Type"); 
     Console.WriteLine("-------------------------------------------------------"); 
     Console.WriteLine("{0}\t{1}\t{2}\t{3}", "str", str, MyClass.Foo(str), MyClass.CallFoo(str)); 
     Console.WriteLine("{0}\t{1}\t\t{2}\t{3}", "num", num, MyClass.Foo(num), MyClass.CallFoo(num)); 
     Console.WriteLine("{0}\t{1}\t{2}\t{3}", "obj", obj, MyClass.Foo(obj), MyClass.CallFoo(obj)); 
    } 

} 

class MyClass 
{ 
    public static Type Foo<T>(T param) 
    { 
     return typeof(T); 
    } 

    public static Type CallFoo(object param) 
    { 
     return (Type)typeof(MyClass).GetMethod("Foo").MakeGenericMethod(new[] { param.GetType() }).Invoke(null, new[] { param }); 
    } 

} 

出力

var  value   Foo() Type  CallFoo() Type 
    ------------------------------------------------------- 
    str  Hello World  System.Object System.String 
    num  5    System.Object System.Int32 
    obj  System.Object System.Object System.Object 
+0

あなたは私のヒーローです:-) –

+0

それは私が認めようとするよりも長くかかりました。時間を節約!ハッピーコーディング:) –

5

これは(私は少しの間でそれをテストします)あなたに呼び出し可能なメソッドを与える必要があります。それが発生するboxing/unboxingはReflection APIの呼び出しに必要なセキュリティチェックよりも速くです(ボクシングも必要です)。

private static Action<MethodInfo, object> BuildAccessor(Type valueType) 
{ 
    MethodInfo genericMethod = null; // <-- fill this in 
    MethodInfo method = genericMethod.MakeGenericMethod(new Type[] { valueType }); 
    ParameterExpression methodInfo = Expression.Parameter(typeof(MethodInfo), "methodInfo"); 
    ParameterExpression obj = Expression.Parameter(typeof(object), "obj"); 

    Expression<Action<MethodInfo, object>> expr = 
     Expression.Lambda<Action<MethodInfo, object>>(
      Expression.Call(method, methodInfo, Expression.Convert(obj, valueType)), 
      methodInfo, 
      obj); 

    return expr.Compile(); 
} 
+0

これもうまくいくはずです:-)ありがとう! タイプを正しくキャストするために、ジェネリックメソッドを動的に呼び出すようになっているようです。 –

+0

これを実証できますか?私はそれがどのように呼び出される必要があるか少し不明です。 –

+0

型が自分自身を解決するために直接メソッドではなく動的にメソッドを呼び出すのと同じです。私はこれが似たようなことをやっていると想像しました。 –

関連する問題