C# 使用运行时类型创建泛型Func委托

C# 使用运行时类型创建泛型Func委托,c#,generics,reflection,delegates,C#,Generics,Reflection,Delegates,我需要调用一个泛型方法,该方法将泛型Func作为其参数之一,其中类型参数仅在运行时已知。这部分代码是一个对象映射器,它在源对象和目标对象之间映射属性。ViewModelBase是被视为“目标”对象的类的根 我要调用的方法(在ObjectMapperBuilder上定义)具有以下签名: public static ObjectMapperBuilder<TTarget> Create( Type sourceType, MappingDirection directi

我需要调用一个泛型方法,该方法将泛型Func作为其参数之一,其中类型参数仅在运行时已知。这部分代码是一个对象映射器,它在源对象和目标对象之间映射属性。ViewModelBase是被视为“目标”对象的类的根

我要调用的方法(在ObjectMapperBuilder上定义)具有以下签名:

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,它可以成功地工作。

这是一个很好的建议,但由于其他原因,我不能采用。