C# 使用运行时类型创建泛型Func委托
我需要调用一个泛型方法,该方法将泛型Func作为其参数之一,其中类型参数仅在运行时已知。这部分代码是一个对象映射器,它在源对象和目标对象之间映射属性。ViewModelBase是被视为“目标”对象的类的根 我要调用的方法(在ObjectMapperBuilder上定义)具有以下签名:C# 使用运行时类型创建泛型Func委托,c#,generics,reflection,delegates,C#,Generics,Reflection,Delegates,我需要调用一个泛型方法,该方法将泛型Func作为其参数之一,其中类型参数仅在运行时已知。这部分代码是一个对象映射器,它在源对象和目标对象之间映射属性。ViewModelBase是被视为“目标”对象的类的根 我要调用的方法(在ObjectMapperBuilder上定义)具有以下签名: public static ObjectMapperBuilder<TTarget> Create( Type sourceType, MappingDirection directi
public static ObjectMapperBuilder<TTarget> Create(
Type sourceType,
MappingDirection direction,
Func<TTarget, IDictionary<String, object>> getDictionaryFromTarget = null
);
公共静态ObjectMapperBuilder创建(
类型sourceType,
映射方向,
Func getDictionaryFromTarget=null
);
在我的基类中,我想调用上面的方法,但使用最派生的类型作为我的类型参数:
public ViewModelBase {
private ConcurrentDictionary<string, object> _propertyValues;
public ViewModelBase (object sourceObject) {
Type tTarget = this.GetType();
// 1. How do I create the Func? All it does is return a private member.
// This is wrong because it uses a compile-time generic parameter.
Func<TTarget,IDictionary<String,object>> myFunc = (vm) => vm._propertyValues;
// 2. Ho do I call the Create method using reflection to specify the
// TTarget generic parameter at runtime?
var myMapper = ObjectMapperBuilder<TTarget>.Create(
sourceObject.GetType(),
MappingDirection.Bidirectional,
myFunc
);
// Do stuff with myMapper.
...
}
公共视图模型库{
私有ConcurrentDictionary_属性值;
公共ViewModelBase(对象源对象){
键入tTarget=this.GetType();
//1.如何创建Func?它只返回一个私有成员。
//这是错误的,因为它使用编译时泛型参数。
Func myFunc=(vm)=>vm.\u属性值;
//2.如何使用反射调用Create方法来指定
//t运行时的目标泛型参数?
var myMapper=ObjectMapperBuilder.Create(
sourceObject.GetType(),
映射方向。双向,
myFunc
);
//用myMapper做一些事情。
...
}
本练习的目的是能够在基类上的方法中创建映射器。必须使用最派生的类型创建映射器,因为我根据源和目标类型缓存映射器,不同的派生类型需要不同的映射器
这可能是表达式树和激活器的工作,但我无法理解
部分答案可以在对该问题的回答中找到:
这可能是一个简单的答案,但您能否将视图模型基类型设置为通用类型,例如:
public class ViewModelBase<T> where T : ViewModelBase<T>
public类ViewModelBase其中T:ViewModelBase
允许您应用继承:
public class SubViewModelBase: ViewModelBase<SubViewModelBase>
公共类子ViewModelBase:ViewModelBase
这样,您的实现将只是:
Func<T, IDictionary<string, object>> props = (vm) => vm._propertyValues;
var mapper = ObjectMapperBuilder<T>.Create(
sourceObject.GetType(),
MappingDirection.Bidirectional,
props);
Func props=(vm)=>vm.\u属性值;
var mapper=ObjectMapperBuilder.Create(
sourceObject.GetType(),
映射方向。双向,
道具);
我找到了一个折衷的解决方案。我创建了一个方法“GetProperties”,它满足了我的需要,然后使用delegate.CreateDelegate将其包装在一个委托中
protected static IDictionary<string, object> GetProperties(ViewModelBase viewModel)
{
return viewModel._propertyValues;
}
protected Delegate GetPropertiesFunc()
{
Type funcType = typeof(Func<,>).MakeGenericType(this.GetType(), typeof(IDictionary<String,object>));
MethodInfo method = typeof(ViewModelBase).GetMethod("GetProperties",
BindingFlags.NonPublic | BindingFlags.Static
);
return Delegate.CreateDelegate(funcType, method);
}
受保护的静态IDictionary GetProperties(ViewModelBase viewModel)
{
返回viewModel.\u属性值;
}
受保护的委托GetPropertiesFunc()
{
Type funcType=typeof(Func).MakeGenericType(this.GetType(),typeof(IDictionary));
MethodInfo method=typeof(ViewModelBase).GetMethod(“GetProperties”,
BindingFlags.NonPublic | BindingFlags.Static
);
返回Delegate.CreateDelegate(functtype,method);
}
当我以后需要将委托作为一个特定的函数时,我调用GetPropertiesFunc并将其传递给Activator.CreateInstance,它可以成功地工作。这是一个很好的建议,但由于其他原因,我不能采用。