投射到C#中的反射类型 [英] Cast to a reflected Type in C#
问题描述
请考虑以下代码:
object objFoo = MakeFoo // Object MakeFoo(){return new Foo();}
MethodInfo methodInfo = typeof(Program).GetMethod(Baz); // Foo Baz(){return foo;}
类型typeFoo = methodInfo.ReturnType;
var result =(typeFoo)objFoo;
我需要做一些魔法与 typeFoo
情况1:
object objFoo = MakeFoo // object MakeFoo(){return new Foo();}
Foo result =(Foo)objFoo;
这里没有反映,因为你知道 Foo
type in compile time。
情况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)
{
//使用foo
}
案例4:键入
Foo
对于您的程序是完全未知的。您没有Foo
类可引用...对象objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
类型typeFoo = objFoo.GetType(); //你应该先检查空值!
//现在?
dynamic foo = objFoo;
//因为你知道foo可以Quack(1,2,3)!
string result = foo.Quack(1,2,3);
//注意,如果没有
//字符串Quack(int,int,int)方法,它会爆炸RuntimeBinderException!
动态
您可以直接使用反射来获得Quack
方法并调用
情况5:如情况4,但使用直接反射:
object objFoo = MakeFoo // object MakeFoo(){return new Foo();}
类型typeFoo = objFoo.GetType(); //你应该先检查空值!
MethodInfo mi = type.GetMethod(Quack); //你应该检查Quack方法
//是否存在
string result =(string)mi.Invoke(objFoo,new object [] {1,2,3});
或者,如果你不确定
foo
可以正确地:
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: c> Foo
Foo
类别。您没有IFoo
界面。你甚至不知道Foo
是什么,你只知道它是一个类(或者是一个盒子struct
,但它不会改变从你的观点...它不能是一个接口
,因为最终总是有一个具体的<$ c $每个接口
后面的class / struct
你不知道它的方法,它的字段,它的属性(因为你不知道Foo
是什么)。
即使你可以向这个未知类施放
对象
,你能做什么?你的代码中不能有方法接受它作为参数/返回值,因为如果你有:int INeedFoo(Foo par){return 0; }
那么你就会知道
Foo
。 .NET库不能有接受它作为参数/返回值的方法,因为如果它有,你会知道Foo
。
你唯一可以做的是将它传递给你通过反射发现接受
Foo
一个参数...但是Invoke
方法接受一个object
作为参数的数组...你不需要投入对象
调用调用
!你只需要把它放在数组中。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
typeFoo
to get the result?解决方案No :-)
Case 1:
object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();} Foo result = (Foo)objFoo;
There is no reflection here, because you know the
Foo
type at compile time.Case 2: interfaces. Normally the best one... You don't know what exactly
MakeFoo
returns, but you know it's anIFoo
interface...object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();} IFoo result = (IFoo)objFoo;
Case 3: you aren't sure
MakeFoo
returnsFoo
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
Foo
is completely unknown to your program. You don't have aFoo
class referenceable...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
dynamic
internally uses reflection. You could use reflection directly to get theQuack
method and call itCase 5: as case 4, but using directly reflection:
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
foo
canQuack
correctly: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
Foo
is completely unknown to your program. You don't have aFoo
class referenceable. You don't have anIFoo
interface. You don't even know what aFoo
is, you know only that it's a class (or perhaps it's a boxedstruct
, but it doesn't change from your point of view... It can't be aninterface
because in the end there must always be a concreteclass
/struct
behind everyinterface
). You don't know of its methods, its fields, its properties (because you don't know whatFoo
is).Even if you can cast an
object
to 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: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 ofFoo
.The only thing you can do is pass it to some other methods that you discover through reflection that accept
Foo
as a parameter... But theInvoke
method accepts an array ofobject
as parameters... You don't need to cast yourobject
to callInvoke
! You only need to put it in the array.这篇关于投射到C#中的反射类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!