简体   繁体   English

如何在C#中使用表示反射结果类型的变量进行转换.Invoke()

[英]How in C# to cast using a variable representing a type for the result of reflection .Invoke()

I have a method that returns byte[] but for now would like to avoid using generics on the method to supply the return type. 我有一个返回byte []的方法但是现在想避免在方法上使用泛型来提供返回类型。 I currently pass a parameter into this method that has the details of the type of the data that will be serialized to the byte[] return result. 我当前将一个参数传递给此方法,该方法具有将序列化为byte []返回结果的数据类型的详细信息。

Question: 题:

How do I perform a dynamic cast of the result of .Invoke() ? 如何对.Invoke()的结果进行动态转换

I'm using reflection to call a method on a class the output of this is object and this result needs to be cast. 我正在使用反射来调用类的方法,这个方法的输出是对象,这个结果需要被强制转换。

The Code: 编码:

public byte[] SomeMethod(/* some params */)
{
    MethodInfo info = /* ... */ .GetMethod(methodToCall);

    //Here I want to perform a dynamic cast:
    return (info.Invoke(classToCall, methodParams)).Serialize();

    //if I was to just have the method fixed to a type it would look like:
    return (info.Invoke(classToCall, methodParams) as SomeType).Serialize();

    //NOTE: .Serialize() is just my own extension method
}

What I have tried without success: 没有成功的尝试

//with returnType as a string
var dynamicType = Type.GetType(returnType);

(info.Invoke(classToCall, methodParams) as dynamicType).Serialize();

Also some other variations with typeof() , GetTypeHandle , .ReflectedType 还有一些其他的变体有typeof()GetTypeHandle.ReflectedType


Am I missing something simple and/or obvious, or am I just trying to do something strange/silly? 我错过了一些简单和/或明显的东西,或者我只是想做一些奇怪/愚蠢的事情?

Additional note: the SomeMethod is an override of a method of a class hence not wanting to have the method support a generic type. 附加说明: SomeMethod是类的方法的重写,因此不希望该方法支持泛型类型。

It is a common misunderstanding that the cast operator really does anything in this situation. 在这种情况下,演员经常做任何事情是一种常见的误解。 You either want to convert from the type that Invoke returned to another type, or it already is the type you want it to be even though Invoke is declared to return object . 您要么 Invoke返回的类型转换为另一种类型,要么即使Invoke被声明为返回object ,它也已经是您希望它的类型。

Since I don't think you want to convert anything, you have to first recognize that the return value of calling Invoke like this: 由于我认为你不想转换任何东西,你必须首先认识到调用Invoke的返回值如下:

var result = info.Invoke(classToCall, methodParams);

the result will be a variable of type object but the value in that variable will already be the type you want to cast it to . result将是object类型的变量,但该变量中的值已经是您要将其强制转换为的类型 You just don't know exactly what it is. 你只是不确切地知道它是什么。 And you need to know what it is to call Serialize . 你需要知道调用Serialize是什么。

Now, you have this extension method, or set of overloaded extension methods that operate on a compile time specified initial this parameter. 现在,你有这样的扩展方法,或一组指定的初始编译时的运作超载扩展方法this参数。 One of them matches the type of the return value of the Invoke call. 其中一个匹配Invoke调用的返回的类型。

In order to choose which of these methods to call, you need to use reflection again to get a MethodInfo matching the right type and just call your Serialize method. 为了选择调用这些方法中的哪一个,您需要再次使用反射来获得与正确类型匹配的MethodInfo ,并只调用您的Serialize方法。 It might help if it weren't an extension method because now you have no easy way to look up the extension method the same way the compiler does at compile time only. 如果它不是扩展方法可能会有所帮助,因为现在您没有简单的方法来查找扩展方法,就像编译器在编译时一样。 Extension method matching is extremely laborious and not suited to dynamic invocation. 扩展方法匹配非常费力,不适合动态调用。

Instead, if you want to use reflection a second time to call Serialize , without having a giant switch statement, then you need to have a utility class with all the Serialize methods as public overloads within that class. 相反,如果你想第二次使用反射来调用Serialize ,而没有巨大的switch语句,那么你需要有一个实用程序类,其中所有的Serialize方法都是该类中的公共重载。 At least that is one way to approach the problem. 至少这是解决问题的一种方法。

2 methods come to mind if you don't want to use generics. 如果您不想使用泛型,我会想到两种方法。

First method would be to cast based on methodToCall. 第一种方法是基于methodToCall进行强制转换。 Not too elegant. 不太优雅。

if (methodToCall == "method1")
  return ((obj1)info.Invoke(classToCall, methodParams)).Serialize();
else if (methodToCall == "method2")
 return ((obj2)info.Invoke(classToCall, methodParams)).Serialize();

Second method would be to create a super class that is inherited by all possible return types of your methodToCall. 第二种方法是创建一个由methodToCall的所有可能返回类型继承的超类。 The super class would have .Serialize() declared and inherited by the sub classes. 超类将具有由子类声明和继承的.Serialize()。

interface mySuperClass
{
  byte[] Serialize();
}

Cast as mySuperClass 演员为mySuperClass

return (info.Invoke(classToCall, methodParams) as mySuperclass).Serialize();

This may not work too well if you have a very large number of possible return types. 如果您有大量可能的返回类型,这可能无法正常工作。 Happy coding. 快乐的编码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM