转换为C#中的反射类型

时间:2013-08-05 07:19:36

标签: c# reflection types casting

请考虑以下代码:

object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
MethodInfo methodInfo = typeof(Program).GetMethod("Baz"); // Foo Baz(){return foo;}
Type typeFoo = methodInfo.ReturnType;
var result = (typeFoo)objFoo;

我是否需要使用typeFoo做一些魔术来获得结果?

3 个答案:

答案 0 :(得分:52)

否: - )

案例1:

object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
Foo result = (Foo)objFoo;

这里没有反映,因为你在编译时知道Foo类型。

案例2:接口。通常是最好的...你不知道究竟MakeFoo返回什么,但你知道它是IFoo接口...

object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
IFoo result = (IFoo)objFoo;

案例3 :您不确定MakeFoo是否会返回Foo

object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}

if (objFoo is Foo)
{
    Foo result = (Foo)objFoo;
}

或类似的

object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}

Foo foo = objFoo as Foo;

if (foo != null)
{
    // use foo
}

案例4:类型Foo对您的程序完全不了解。您没有Foo类可引用...

object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
Type typeFoo = objFoo.GetType(); // You should check for null values before!

// and now?

dynamic foo = objFoo;

// because you know that foo can Quack(1, 2, 3)!
string result = foo.Quack(1, 2, 3); 

// note that it will explode with a RuntimeBinderException if there is no 
// string Quack(int, int, int) method!

dynamic内部使用反射。您可以直接使用反射来获取Quack方法并将其命名为

案例5:如案例4,但使用直接反映:

object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
Type typeFoo = objFoo.GetType(); // You should check for null values before!
MethodInfo mi = type.GetMethod("Quack"); // You should check if the Quack method
                                         // exists
string result = (string)mi.Invoke(objFoo, new object[] { 1, 2, 3 });

或者,通过一些完整性检查,如果您不确定foo可以Quack正确:

MethodInfo mi = type.GetMethod("Quack", 
                    BindingFlags.Instance | BindingFlags.Public, 
                    null, 
                    new[] { typeof(int), typeof(int), typeof(int) }, 
                    null);

if (mi != null && typeof(string).IsAssignableFrom(mi.ReturnType))
{
    string result = (string)mi.Invoke(objFoo, new object[] { 1, 2, 3 });
}

案例-Infinity:类型Foo对您的程序完全不了解。您没有Foo类可引用。您没有IFoo界面。你甚至不知道Foo是什么,你只知道它是一个类(或者它可能是一个盒装的struct,但它并没有从你的角度改变......它可以不是interface,因为最终每个class后面必须始终有一个具体的struct / interface。你不知道它的方法,它的字段,它的属性(因为你不知道Foo是什么)。

即使你可以将object投射到这个未知的类,你还能做什么?您不能在代码中使用接受它作为参数/返回值的方法,因为如果您拥有某个地方:

int INeedFoo(Foo par) { return 0; }
那么显然你会知道Foo。 .NET库不能有接受它作为参数/返回值的方法,因为如果有,你会知道Foo

您唯一能做的就是将其传递给您通过接受Foo作为参数的反射发现的其他方法......但Invoke方法接受{{1}的数组}作为参数...您无需强迫object来调用object!你只需要把它放在数组中。

答案 1 :(得分:1)

这相当于:

object objFoo = MakeFoo();
Foo result = (Foo)objFoo;

将对象转换为在编译时未知的类型没有任何意义 - 您将无法使用它:

object objFoo = MakeFoo();
UnkownType result = (UknownType)objFoo;

由于您不知道UknownType是什么,如果不采用反射或动态,您将无法使用任何方法。

答案 2 :(得分:0)

这是google中有关转换为反射类型的第一个结果。

因此,为了供参考,以防万一sb想知道将哪种类型转换为反射类型的一般方法:

public static T CastTo<T>(this object o) => (T)o;

public static dynamic CastToReflected(this object o, Type type)
{
    var methodInfo = typeof(ObjectExtensions).GetMethod(nameof(CastTo), BindingFlags.Static | BindingFlags.Public);
    var genericArguments = new[] { type };
    var genericMethodInfo = methodInfo?.MakeGenericMethod(genericArguments);
    return genericMethodInfo?.Invoke(null, new[] { o });
}