情况: 类型baseType仅在运行时已知。 objectInstance是baseType类型的子级。 objectInstance是从对动态方法的调用中检索的。
Situation: Type baseType known only at runtime. objectInstance is a child of type baseType objectInstance was retrieved from a call to a dynamic method
必需:
Type baseType = ...; // obtained at runtime var baseDynamicInstance = (basetype) objectInstance; // or reflection cast当进行硬编码时,它起作用
when hardcoded, it works
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; }错误: 空对象引用错误。 在即时窗口中看到objectInstance.GetType()。GetMethod( Cast)返回null objectInstance.GetType.GetMethods()//在即时窗口中显示列表。 //未显示强制转换方法
ERROR: null object ref error. in immediate window i see objectInstance.GetType().GetMethod("Cast") returns null objectInstance.GetType.GetMethods() // shows a list in immediate window. // no cast method shown
我看过很多示例这对我来说建议使用Type.GetMethod( Cast)正确。 但是它没有用。所以很明显我做错了。
I have looked at many examples That would suggest to me the Type.GetMethod("Cast") was correct. But it doesnt work.So clearly im doing something wrong.
任何提示
编辑: 没有向下转换为基本硬编码的调用错误
The call error without the down cast to base hardcoded
[Microsoft.CSharp.RuntimeBinder.RuntimeBinderException] = { 的重载方法匹配'P42.RepositoryBase.GetEntityState(P42.Core.PartnerBase)'有一些无效的参数}
[Microsoft.CSharp.RuntimeBinder.RuntimeBinderException] = {"The best overloaded method match for 'P42.RepositoryBase.GetEntityState(P42.Core.PartnerBase)' has some invalid arguments"}
EDIT2: 从动态方法调用中检索ObjectInstance。 该对象应在对动态方法的调用中使用。 如果我硬编码向下转换,它会起作用。 var x =(基础对象)ObjInstance 并使用x调用动态方法。
AN ObjectInstance is retrieved from a dynamic method call. 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. it Works.
也只能在运行时知道基本类型。 是否可以动态地将SpecificObject强制转换为BAseObject?
The base type is also only known at runtime. Is there a way to cast SpecificObject to BAseObject dynamically?
推荐答案将类型强制转换为仅在运行时才知道的类型对编译器来说是毫无意义的操作:由于定义上直到运行时才知道类型,因此没有编译时支持,因此这样做没有任何好处。如果通过反射使用对象,则保存实例的变量的实际类型无关紧要-最好是 Object 。
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.
这并不意味着不可能,执行转换只是有点麻烦。该语言的确使我们能够使用类型参数化的类型编写仅在运行时才知道给定类型的代码!
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!
我的示例中的代码设置了一个非常简单的方法使用运行时专有的信息来获取 LibraryDelegate< TRunTimeType> 的 AdapterDelegate 。您会在 AdapterDelegateHelper.Adapter< TRuntimeType> .adapter 方法中注意到对 TRunTimeType 的实际转换。查看 Main 代码以查看它的易用性:
The code in my example sets a very simple method to obtain an AdapterDelegate for a LibraryDelegate<TRunTimeType>, using information exclusively found at runtime. You'll notice the actual cast to TRunTimeType in the AdapterDelegateHelper.Adapter<TRuntimeType>.adapter method. Look at the Main code to see how easy this is to use:
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(); } } }更多推荐
动态对象强制转换为仅在运行时已知的类型
发布评论