转换为 C# 中的反射类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18052562/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 11:09:04  来源:igfitidea点击:

Cast to a reflected Type in C#

c#reflectiontypescasting

提问by user2341923

Consider the following code:

考虑以下代码:

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;

Do I need to do some magic with typeFooto get the result?

我需要做一些魔法typeFoo才能得到结果吗?

采纳答案by xanatos

No :-)

不 :-)

Case 1:

情况1:

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

There is no reflection here, because you know the Footype at compile time.

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

Case 2:interfaces. Normally the best one... You don't know what exactly MakeFooreturns, but you know it's an IFoointerface...

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

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

Case 3:you aren't sure MakeFooreturns Foo

案例 3:你不确定MakeFoo回报Foo

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

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

or, similar

或者,类似的

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

Foo foo = objFoo as Foo;

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

Case 4:type Foois completely unknown to your program. You don't have a Fooclass referenceable...

情况 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!

the dynamicinternally uses reflection. You could use reflection directly to get the Quackmethod and call it

dynamic内部使用反射。您可以直接使用反射来获取Quack方法并调用它

Case 5:as case 4, but using directly reflection:

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

or, with some sanity checks, if you aren't sure foocan Quackcorrectly:

或者,通过一些健全性检查,如果您不确定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:type Foois completely unknown to your program. You don't have a Fooclass referenceable. You don't have an IFoointerface. You don't even know what a Foois, you know only that it's a class (or perhaps it's a boxed struct, but it doesn't change from your point of view... It can't be an interfacebecause in the end there must always be a concrete class/structbehind every interface). You don't know of its methods, its fields, its properties (because you don't know what Foois).

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

Even if you can cast an objectto this unknown class, what can you do? You can't have methods in your code that accept it as a parameter/return value, because if somewhere you had:

即使您可以将 an 转换object为这个未知的类,您能做什么?你的代码中不能有方法接受它作为参数/返回值,因为如果你有:

int INeedFoo(Foo par) { return 0; }

then clearly you would know of Foo. The .NET library can't have methods that accept it as a parameter/return value, because if it had, you would know of Foo.

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

The only thing you can do is pass it to some other methods that you discover through reflection that accept Fooas a parameter... But the Invokemethod accepts an array of objectas parameters... You don't need to cast your objectto call Invoke! You only need to put it in the array.

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

回答by zmbq

This would be equivalent to:

这相当于:

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

There's no real point in casting an object to a type that's unknown at compile time - you won't be able to use it:

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

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

Since you don't know what UknownTypeis, you won't be able to use any of its methods without resorting to reflection, or to dynamics.

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

回答by rvnlord

This is the first result in google about Casting to a reflected type.

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

So for reference, in case sb wonders what would be a general way of casting to a reflected type:

所以作为参考,如果某人想知道转换为反射类型的一般方法是什么:

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