gpt4 book ai didi

c# - 动态对象转换为仅在运行时已知的类型

转载 作者:太空狗 更新时间:2023-10-29 23:23:13 51 4
gpt4 key购买 nike

情况: 类型 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;
}

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

我看了很多例子这向我表明 Type.GetMethod("Cast") 是正确的。但它不起作用。很明显我做错了什么。

任何提示

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

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

编辑 2:一个 ObjectInstance 从动态方法调用中检索。该对象应该在对动态方法的调用中使用。如果我硬编码下来,它就可以工作。 var x = (baseobject) ObjInstance并使用 x 调用动态方法。它有效。

基类型也只在运行时才知道。有没有办法将 SpecificObject 动态转换为 BAseObject?

最佳答案

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

这并不意味着它不可能,只是做 Actor 有点麻烦。该语言确实允许我们使用类型参数化类型编写仅在运行时识别给定类型的代码!

我示例中的代码设置了一个非常简单的方法来获取 AdapterDelegate对于 LibraryDelegate<TRunTimeType> ,使用在运行时专门找到的信息。您会注意到实际转换为 TRunTimeTypeAdapterDelegateHelper.Adapter<TRuntimeType>.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>(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();
}
}
}

关于c# - 动态对象转换为仅在运行时已知的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19200492/

51 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com