簡體   English   中英

獲取通用對象參數的實際類型

[英]Get the actual type of a generic object parameter

毫無疑問,這個問題的元素之前已被問過,但我找不到答案。 (免責聲明:這是相關的,但與我最近提出的問題不同)。

我有這樣的方法:

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);

但是,我需要使用泛型類型調用此方法,所以我這樣調用它:

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

現在,intellisense知道Method <T>中的'value'是valueType的任何類型(比如說'FooObject')。 但是'T'是對象,這意味着List <FooObject> 不能從List <T>(即List <object>)分配。

我已經嘗試事先在變量('passValue')上使用Convert.ChangeType,但這沒有任何用處。

由於無法將變量強制轉換為類型變量的類型,我該如何解決這個問題呢?

最好的解決方案是以某種方式不依賴於IsAssignableFrom並做一個更寬松的類型檢查這是否有效? 這個問題是我不確定我是否能夠正確地轉換memberValue,除非'T'確實是memberValue的元素類型。

這應該給你一個可調用的方法(我會在一段時間內測試它)。 它引發的裝箱/拆箱比反映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();
}

你很幸運。 幾周前我實際上不得不做一些非常相似事情

有關詳細說明,請參閱上面的博客文章,但基本上一般的想法是反映類型並使用一組顯式參數手動調用該方法。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM