24

考虑以下代码:

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才能得到结果吗?

4

3 回答 3

62

不 :-)

情况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 });
}

Case -Infinity:Foo您的程序完全不知道 类型。您没有可Foo引用的类。你没有IFoo接口。你甚至不知道 aFoo是什么,你只知道它是一个类(或者它可能是一个 boxed struct,但从你的角度来看它并没有改变......它不可能是 ainterface因为最后必须永远是一个具体的class/struct在每一个之后interface)。你不知道它的方法、字段、属性(因为你不知道是什么Foo)。

即使你可以object向这个未知的班级投一个,你能做什么?你的代码中不能有接受它作为参数/返回值的方法,因为如果你在某个地方有:

int INeedFoo(Foo par) { return 0; }

那么显然你会知道Foo。.NET 库不能有接受它作为参数/返回值的方法,因为如果有,你就会知道Foo.

你唯一能做的就是将它传递给你通过反射发现的其他一些接受Foo作为参数的方法......但是该Invoke方法接受一个数组object作为参数......你不需要强制object调用Invoke!您只需要将其放入数组中。

于 2013-08-05T07:24:28.840 回答
8

这是谷歌关于投射到反射类型的第一个结果。

因此,作为参考,如果 sb 想知道转换为反射类型的一般方法是什么:

public static class ObjectExtensions
{
    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 });
    }
}
于 2019-04-25T15:29:04.727 回答
1

这相当于:

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

将对象强制转换为编译时未知的类型没有真正意义——您将无法使用它:

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

由于您不知道它是什么UknownType,因此如果不借助反射或动态,您将无法使用它的任何方法。

于 2013-08-05T07:25:01.190 回答