C# 非专利药及;静态类。实现查询助手方法

C# 非专利药及;静态类。实现查询助手方法,c#,generics,extension-methods,automapper,C#,Generics,Extension Methods,Automapper,目前,我们实现了这样一个映射服务(该服务使用automapper,我们在这一部分中使用了它的投影功能) //注入 //IGenericRepository entityRepo var query=this.entityRepo .FindAll(a=>a.Id==someId) .采取(1)项措施; var result=this.mappingService .Map(查询) .FirstOrDefault(); 我想创建一个扩展,允许我执行以下操作 var result = this.e

目前,我们实现了这样一个映射服务(该服务使用automapper,我们在这一部分中使用了它的投影功能)

//注入
//IGenericRepository entityRepo
var query=this.entityRepo
.FindAll(a=>a.Id==someId)
.采取(1)项措施;
var result=this.mappingService
.Map(查询)
.FirstOrDefault();
我想创建一个扩展,允许我执行以下操作

var result = this.entityRepo
                 .FindAll(a => a.Id == someId)
                 .Take(1).Map<EntityDto>()   <--- Entity inferred from repo type
                 .FirstOrDefault();
var result=this.entityRepo
.FindAll(a=>a.Id==someId)
.Take(1.Map()a.Id==someId)
.Take(1.Map)()
.FirstOrDefault();
问题:

 public static class IQueryableExtensions
 {
     private static IMappingService mappingService;

     // will need to be called in app initialization
     public static void InitialiseMapper(IMappingService service)
     {
         mappingService = service;
     }

     public static IEnumerable<TDto> Map<TAttribute, TDto>(this IQueryable<TAttribute> value)
            where TDto : class
            where TAttribute : IEntity
     {
        return mappingService.Map<TAttribute, TDto>(value);
     }
 }
1) 如何从IQueryable对象推断实体类型

2) 我意识到在创建静态类时,我不能创建一个带参数的构造函数。我初始化映射器的方法是最好的/唯一的方法吗?

1)目前,在C#中根本无法做到这一点。类型推断不够好。可以指定所有类型参数,也可以不指定任何类型参数

编辑:如果您真的希望版本具有单个参数,则必须删除第二个类型参数,将该参数键入非泛型
IQueryable
,然后处理它。一种方法是在运行时确定泛型
IQueryable
类型。然而,这需要反思。对于
IQueryable
,您还可以使用查询提供程序绕过反射

2) 您可以使用静态类型构造函数

public static class MyExtensions {
    static MyExtensions() {
        //initialization goes here
    }
}

这种类型的构造函数甚至被称为线程安全的。但是,如果您设法在此处引发异常,则无法访问
MyExtensions

我试着反省一下。这些约束仅用于演示。如果要多次调用反射代码,请确保缓存最终的methodinfo

void Main()
{
    var a = new Entity[] {new Entity { name = "a"},new Entity { name = "b"}};

    Console.WriteLine(a.Take(1).Map<EntityDto>());
}

public class Entity
{
    public string name;
}

public class EntityDto
{
    public string dtoname;

}

public static class EntityExtensions
{
    public static IEnumerable<U> Map<T,U>(this IEnumerable<T> e) where T: Entity where U: EntityDto, new()
    {
        foreach(var a in e)
        {
            yield return new U() { dtoname = a.name };
        }
    }


    public static IEnumerable<U> Map<U>(this IEnumerable<object> e)
    {
        var method = typeof(EntityExtensions).GetMethods(BindingFlags.Static | BindingFlags.Public)     
        .Where(m => m.Name == "Map" && m.GetGenericArguments().Length == 2)
        .Single();
        method = method.MakeGenericMethod(e.GetType().GetGenericArguments()[0], typeof(U));

        return method.Invoke(null, new object[] { e}) as IEnumerable<U>;
    }
}
void Main()
{
var a=新实体[]{new Entity{name=“a”},新实体{name=“b”};
Console.WriteLine(a.Take(1.Map());
}
公共类实体
{
公共字符串名称;
}
公共类实体
{
公共字符串dtoname;
}
公共静态类EntityExtensions
{
公共静态IEnumerable映射(此IEnumerable e),其中T:Entity,其中U:EntityDto,new()
{
foreach(e中的var a)
{
返回新的U(){dtoname=a.name};
}
}
公共静态IEnumerable映射(此IEnumerable e)
{
var method=typeof(EntityExtensions).GetMethods(BindingFlags.Static | BindingFlags.Public)
.Where(m=>m.Name==“Map”&&m.GetGenericArguments().Length==2)
.Single();
method=method.MakeGenericMethod(e.GetType().GetGenericArguments()[0],typeof(U));
作为IEnumerable返回方法.Invoke(null,新对象[]{e});
}
}

我不知道是否只有我一个人,也不知道我是否看错了。你到底为什么要使用
.Take(1)
.FirstOrDefault()
,难道你不能直接使用
.FirstOrDefault(a=>a.Id==someId).Map
?您也不能更改
Map()
方法并将其更改为
MapFirstOrDefault()
,然后在助手类中执行第一个或默认值,因为您已经完成了编写扩展方法的工作。Take(1),仍将返回集合和FirstOrDefault(),获取第一个项并将其映射到您的实体类型。但在本例中,Take(1),&FirstOrDefault()与问题无关,只是作为查询的一个示例。。。由于我的问题与映射部分有关,例如IQueryable to IEnumerableSo,让我看看这次是否正确?你的意思是,这个代码
返回mappingService.Map(value)
没有返回一个
IEnumerable
,但您希望它返回
IEnumerable
?我想将调用语法从:.Map(查询)更改为.Map()。查询提供程序的方法类似于
public static class MyExtensions {
    static MyExtensions() {
        //initialization goes here
    }
}
void Main()
{
    var a = new Entity[] {new Entity { name = "a"},new Entity { name = "b"}};

    Console.WriteLine(a.Take(1).Map<EntityDto>());
}

public class Entity
{
    public string name;
}

public class EntityDto
{
    public string dtoname;

}

public static class EntityExtensions
{
    public static IEnumerable<U> Map<T,U>(this IEnumerable<T> e) where T: Entity where U: EntityDto, new()
    {
        foreach(var a in e)
        {
            yield return new U() { dtoname = a.name };
        }
    }


    public static IEnumerable<U> Map<U>(this IEnumerable<object> e)
    {
        var method = typeof(EntityExtensions).GetMethods(BindingFlags.Static | BindingFlags.Public)     
        .Where(m => m.Name == "Map" && m.GetGenericArguments().Length == 2)
        .Single();
        method = method.MakeGenericMethod(e.GetType().GetGenericArguments()[0], typeof(U));

        return method.Invoke(null, new object[] { e}) as IEnumerable<U>;
    }
}