Casting a dynamic object to a type known only at run time

Situation: The baseType type is known only at runtime. objectInstance - this is a type of type baseType objectInstance was obtained from a call to a dynamic method

It is required:

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

when it is encoded, 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 the next window, I see objectInstance.GetType (). GetMethod ("Cast") returns null
objectInstance.GetType.GetMethods () // shows the list in the immediate window. // casting method not shown

I have looked at many examples. This tells me that Type.GetMethod ("Cast") was right. But that does not work. It’s clear that I’m doing something wrong.

Any advice

EDIT: Call failed without casting down to a base hard-set

[Microsoft.CSharp.RuntimeBinder.RuntimeBinderException] = {"The best overloaded method match for 'P42.RepositoryBase.GetEntityState (P42.Core.PartnerBase)' has some invalid arguments"}

EDIT2: AN ObjectInstance is retrieved from a call to a dynamic method. The object must be used when invoking a dynamic method. If it's hard for me to write code, it works. var x = (base object) ObjInstance And call the dynamic method using x. it works.

The base type is also known only at run time. Is there a way to dynamically allocate a SpecificObject for a BAseObject?

+6
source share
2 answers

Casting to a type known only in Runtime seems like a meaningless operation for the compiler: since by definition it does not know the type before Runtime, there is no compilation time support, so there is no use in it. If an object is used through Reflection, then the actual type of the variable, which contains an instance, does not really matter - there may also be an Object .

This does not mean that it is impossible, it is just a little cumbersome to do. The language allows us to write code that only informs about a given type at runtime using types of parameterized types!

The code in my example sets up a very simple method to get AdapterDelegate for LibraryDelegate<TRunTimeType> using information exclusively found at runtime. You will notice the actual tide of TRunTimeType in the AdapterDelegateHelper.Adapter<TRuntimeType>.adapter . Look at the Main code to see how easy it 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(); } } } 
+4
source

You can try dynamic if you are working on .Net4.0.

-2
source

Source: https://habr.com/ru/post/955307/


All Articles