非通用委托的适配器

时间:2019-02-19 10:11:30

标签: c# lambda reflection

我有一个通用类:

public class ProviderAdapter<TDto, TModel>
{
    public ProviderAdapter(IQueryable source, Func<TDto, TModel> mapping)
    {
      ... //not important
    }
}

和扩展方法:

public static class QueryableExtensions
{
    public static IQueryable<TModel> Map<TDto, TModel>(
        this IQueryable<TDto> query, Func<TDto, TModel> mapping)
    {
      var providerAdapter = new ProviderAdapter<TDto, TModel>(query, mapping);
      var result = new QueryableAdapter<TModel>(providerAdapter);
      return result;
    }
}

现在,我想为非通用IQueryable创建另一种扩展方法:

public static class QueryableExtensions
{
    public static IQueryable<TModel> Map<TModel>(
        this IQueryable query, Func<dynamic, TModel> mapping)
    {
      //how to create ProviderAdapter instance having 
      //query.ElementType and mapping Func with dynamic?
      var providerAdapter = new ProviderAdapter<type from query.ElementType, TModel>(query, 
      new Func<type from query.ElementType, TModel> using mapping Func<dynamic,TModel>
    }
}

有可能吗?我不确定'mapping'参数类型-我打算使用调用

的反射来创建新的Func。
Func<dynamic, TModel> 

但是将第一个参数转换为query.ElementType。也许'mapping'参数应该是

类型
Expression<Func<dynamic, TModel>>

1 个答案:

答案 0 :(得分:2)

如果我正确理解了您的问题,我会这样做:

public static class QueryableExtensions2
{
    public static IQueryable<TModel> Map<TModel>(
        this IQueryable query, Func<dynamic, TModel> mapping)
    {
        var tdto = query.ElementType;
        var typedMapping =
            typeof(QueryableExtensions2).GetMethod(nameof(Wrap))
                                        .MakeGenericMethod(tdto, typeof(TModel))
                                        .Invoke(null, new object[] { mapping });

        var targetType = typeof(ProviderAdapter<,>)
                             .MakeGenericType(tdto, typeof(TModel));
        var instance = Activator.CreateInstance(targetType,
                                                new object[] { query, typedMapping });
        return (IQueryable<TModel>)instance;
    }

    static public Func<TDto, TModel> Wrap<TDto, TModel>(Func<dynamic, TModel> mapping) =>
        d => mapping(d);
}