[英]Dynamic object cast to type known at runtime only
Situation: Type baseType known only at runtime. 情况:类型baseType仅在运行时已知。 objectInstance is a child of type baseType objectInstance was retrieved from a call to a dynamic method
objectInstance是baseType类型的子对象objectInstance是从对动态方法的调用中检索的
Required: 需要:
Type baseType = ...; // obtained at runtime
var baseDynamicInstance = (basetype) objectInstance; // or reflection cast
when hardcoded, it works 硬编码后,它可以工作
var oi = (PartnerBase) objectInstance; // this works
tried: 尝试过:
public object CastPocoInstance(Type targetType, object objectInstance) {
MethodInfo castMethod = objectInstance.GetType().GetMethod("Cast").MakeGenericMethod(targetType); // <<< NULL REF here
object castedObject = castMethod.Invoke(null, new object[] { objectInstance });
return castedObject;
}
ERROR: null object ref error. 错误:空对象引用错误。
in immediate window i see objectInstance.GetType().GetMethod("Cast") returns null 在即时窗口中,我看到objectInstance.GetType()。GetMethod(“ Cast”)返回null
objectInstance.GetType.GetMethods() // shows a list in immediate window. objectInstance.GetType.GetMethods()//在立即窗口中显示一个列表。 // no cast method shown
//没有显示强制转换方法
I have looked at many examples That would suggest to me the Type.GetMethod("Cast") was correct. 我看了很多例子,这些例子向我暗示Type.GetMethod(“ Cast”)是正确的。 But it doesnt work.So clearly im doing something wrong.
但是它不起作用,所以很明显我做错了。
Any tips 有小费吗
EDIT: The call error without the down cast to base hardcoded 编辑:没有向下转换为基本硬编码的调用错误
[Microsoft.CSharp.RuntimeBinder.RuntimeBinderException] = {"The best overloaded method match for 'P42.RepositoryBase.GetEntityState(P42.Core.PartnerBase)' has some invalid arguments"}
[Microsoft.CSharp.RuntimeBinder.RuntimeBinderException] = {“'P42.RepositoryBase.GetEntityState(P42.Core.PartnerBase)'的最佳重载方法匹配具有一些无效的参数“”}
EDIT2: AN ObjectInstance is retrieved from a dynamic method call. 编辑2:从动态方法调用中检索ObjectInstance。 The object should be used in a call to a dynamic method.
该对象应在对动态方法的调用中使用。 If I hard code down cast it works.
如果我硬编码向下转换,则可以正常工作。 var x = (baseobject) ObjInstance And call the dynamic method using x.
var x =(基础对象)ObjInstance并使用x调用动态方法。 it Works.
有用。
The base type is also only known at runtime. 基本类型也仅在运行时已知。 Is there a way to cast SpecificObject to BAseObject dynamically?
有没有一种方法可以将SpecificObject动态转换为BAseObject?
Casting to a type that's known only at Runtime seems to be a senseless operation for the compiler: since by definition it doesn't know the type until Runtime, there's no compile-time support for it so there's no benefit in doing so. 强制转换为仅在运行时才知道的类型对于编译器来说似乎是毫无意义的操作:由于按照定义,直到运行时才知道该类型,因此没有编译时支持,因此这样做没有任何好处。 If the object is used through Reflection, then the actual Type of the variable that holds the instance doesn't matter much - might as well be
Object
. 如果通过反射使用该对象,则保存该实例的变量的实际Type无关紧要-也可能是
Object
。
That doesn't mean it's not possible, it's just a bit cumbersome to do the cast. 这并不意味着不可能,执行转换只是有点麻烦。 The language does allow us to write code that's only made aware of a given type at Runtime, using type-parametrised types!
该语言的确允许我们使用类型参数化的类型编写仅在运行时才知道给定类型的代码!
The code in my example sets a very simple method to obtain an AdapterDelegate
for a LibraryDelegate<TRunTimeType>
, using information exclusively found at runtime. 我的示例中的代码设置了一个非常简单的方法,使用在运行时专有的信息来获取
AdapterDelegate
LibraryDelegate<TRunTimeType>
。 You'll notice the actual cast to TRunTimeType
in the AdapterDelegateHelper.Adapter<TRuntimeType>.adapter
method. 您会在
AdapterDelegateHelper.Adapter<TRuntimeType>.adapter
方法中注意到对TRunTimeType
的实际AdapterDelegateHelper.Adapter<TRuntimeType>.adapter
。 Look at the Main
code to see how easy this is to use: 查看
Main
代码,以了解它的易用性:
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Reflection;
namespace ConsoleApplication2
{
// Start by declaring a delegate that looks exactly like the library method you want to call, but with TRuntimeType in place of the actual type
public delegate void LibraryDelegate<TRuntimeType>(TRuntimeType param, Int32 num, String aStr);
// Declare an "adapter" delegate that uses "Object" in place of TRuntimeType for every relevant parameter
public delegate void AdapterDelegate(Object param, Int32 num, String aStr);
public static class AdapterDelegateHelper
{
private class Adapter<TRuntimeType>
{
private readonly LibraryDelegate<TRuntimeType> libDelegate;
public Adapter(Object LibraryInstance, String MethodName)
{
Type libraryType = LibraryInstance.GetType();
Type[] methodParameters = typeof(LibraryDelegate<TRuntimeType>).GetMethod("Invoke").GetParameters().Select(p => p.ParameterType).ToArray();
MethodInfo libMethod = libraryType.GetMethod(MethodName, methodParameters);
libDelegate = (LibraryDelegate<TRuntimeType>) Delegate.CreateDelegate(typeof(LibraryDelegate<TRuntimeType>), LibraryInstance, libMethod);
}
// Method that pricecly matches the adapter delegate
public void adapter(Object param, Int32 num, String aStr)
{
// Convert all TRuntimeType parameters.
// This is a true conversion!
TRuntimeType r_param = (TRuntimeType)param;
// Call the library delegate.
libDelegate(r_param, num, aStr);
}
}
public static AdapterDelegate MakeAdapter(Object LibraryInstance, String MethodName, Type runtimeType)
{
Type genericType = typeof(Adapter<>);
Type concreteType = genericType.MakeGenericType(new Type[] { runtimeType });
Object obj = Activator.CreateInstance(concreteType, LibraryInstance, MethodName);
return (AdapterDelegate)Delegate.CreateDelegate(typeof(AdapterDelegate), obj, concreteType.GetMethod("adapter"));
}
}
// This class emulates a runtime-identified type; I'll only use it through reflection
class LibraryClassThatIOnlyKnowAboutAtRuntime
{
// Define a number of oberloaded methods to prove proper overload selection
public void DoSomething(String param, Int32 num, String aStr)
{
Console.WriteLine("This is the DoSomething overload that takes String as a parameter");
Console.WriteLine("param={0}, num={1}, aStr={2}", param, num, aStr);
}
public void DoSomething(Int32 param, Int32 num, String aStr)
{
Console.WriteLine("This is the DoSomething overload that takes Integer as a parameter");
Console.WriteLine("param={0}, num={1}, aStr={2}", param, num, aStr);
}
// This would be the bad delegate to avoid!
public void DoSomething(Object param, Int32 num, String aStr)
{
throw new Exception("Do not call this method!");
}
}
class Program
{
static void Main(string[] args)
{
Type castToType = typeof(string);
Type libraryTypeToCall = typeof(LibraryClassThatIOnlyKnowAboutAtRuntime);
Object obj = Activator.CreateInstance(libraryTypeToCall);
AdapterDelegate ad1 = AdapterDelegateHelper.MakeAdapter(obj, "DoSomething", castToType);
ad1("param", 7, "aStr");
Console.ReadKey();
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.