简体   繁体   English

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

[英]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.

相关问题 动态调度按类型仅在运行时已知 - Dynamic dispatch by Type only known at runtime 创建一个仅在运行时才知道的类类型的新实例,并根据给定的对象进行转换 - Create a new instance of a class type only known at runtime, and cast it, based on a given object 如何在运行时知道类型时将对象强制转换为类型? - How to cast to an object to a type when type is known during runtime? 将FormCollection转换为仅在运行时已知的类型的对象 - Convert FormCollection to object of type known only at runtime 将对象转换为仅在运行时已知的类型变量 - Casting object to type into variable of said type known only at runtime 处理只能在运行时才能知道的某种类型的对象? - Dealing with an object of certain type, that can be known in runtime only? 在运行时将对象转换为通用类型 - Cast object to generic type at runtime 如何将对象转换为未知的通用类型? - How to cast an object to a not known generic type? 在除运行时外,不知道其泛型类型的对象上的调用方法? 我应该只使用动态效果吗? - Call method on object on which generic type is not known except at runtime? Should I just use a dynamic? 访问类型在运行时已知的对象的属性 - Accessing property of an object whose type is known at runtime
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM