动态对象强制转换为仅在运行时已知的类型

情境:键入baseType仅在运行时知道。 objectInstance是baseType类型的子类,objectInstance是从对动态方法的调用中检索的

需要:

Type baseType = ...; // obtained at runtime var baseDynamicInstance = (basetype) objectInstance; // or reflection cast 

硬编码时,它的工作原理

  var oi = (PartnerBase) objectInstance; // this works 

尝试:

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

错误: null对象引用错误。
在即时窗口中,我看到objectInstance.GetType()。GetMethod(“Cast”)返回null
objectInstance.GetType.GetMethods()//在即时窗口中显示一个列表。 //没有显示强制转换方法

我看了很多例子,这对我来说是Type.GetMethod(“Cast”)是正确的。 但它不起作用。显然我做错了什么。

有小费吗

编辑:没有向下转换为基本硬编码的调用错误

[Microsoft.CSharp.RuntimeBinder.RuntimeBinderException] = {“’P42.RepositoryBase.GetEntityState(P42.Core.PartnerBase)’的最佳重载方法匹配’有一些无效的参数”}

EDIT2:从动态方法调用中检索ObjectInstance。 该对象应该用于调用动态方法。 如果我硬编码下来就可以了。 var x =(baseobject)ObjInstance并使用x调用动态方法。 有用。

基本类型也仅在运行时已知。 有没有办法动态地将SpecificObject强制转换为BAseObject?

转换为仅在运行时已知的类型似乎对编译器来说是一种无意义的操作:因为根据定义,它在运行时之前不知道类型,因此没有编译时支持它因此这样做没有任何好处。 如果通过Reflection使用对象,那么保存实例的变量的实际类型并不重要 – 可能也是Object

这并不意味着它不可能,演员表演有点麻烦。 该语言允许我们使用类型参数化类型编写仅在运行时知道给定类型的代码!

我的示例中的代码使用在运行时专门找到的信息设置了一个非常简单的方法来获取AdapterDelegate LibraryDelegate 。 你会注意到在AdapterDelegateHelper.Adapter.adapter方法中对AdapterDelegateHelper.Adapter.adapter的实际AdapterDelegateHelper.Adapter.adapter 。 查看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 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 { private readonly LibraryDelegate libDelegate; public Adapter(Object LibraryInstance, String MethodName) { Type libraryType = LibraryInstance.GetType(); Type[] methodParameters = typeof(LibraryDelegate).GetMethod("Invoke").GetParameters().Select(p => p.ParameterType).ToArray(); MethodInfo libMethod = libraryType.GetMethod(MethodName, methodParameters); libDelegate = (LibraryDelegate) Delegate.CreateDelegate(typeof(LibraryDelegate), 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(); } } } 

如果使用.Net4.0,您可以尝试dynamic