仿制药&静态类。实现查询帮助器方法 [英] Generics & static classes. Implement query helper method
问题描述
目前我们实现了一个像这样的映射服务(该服务使用了automapper,并且我们利用它的投影功能来完成这部分)
//注入
// IGenericRepository< Entity> entityRepo
var query = this.entityRepo
.FindAll(a => a.Id == someId)
.Take(1);
var result = this.mappingService
.Map< Entity,EntityDto>(query)
.FirstOrDefault();
我想创建一个扩展名,允许我执行以下操作 strong>
var result = this.entityRepo
.FindAll(a => a.Id == someId)
.Take(1).Map< EntityDto>()< ---从回购类型
.FirstOrDefault()推导出的实体;
我目前的尝试:
public static class IQueryableExtensions
{
private static IMappingService mappingService;
//需要在应用程序初始化时调用
public static void InitialiseMapper(IMappingService service)
{
mappingService = service;
}
public static IEnumerable< TDto>映射< TAttribute,TDto>(这个IQueryable< TAttribute>值)
其中TDto:class
其中TAttribute:IEntity
{
返回mappingService.Map< TAttribute,TDto> );
因此,目前我的实现看起来像这样。
var result = this.entityRepo
.FindAll(a => a.Id = = someId)
.Take(1).Map< Entity,EntityDto>()
.FirstOrDefault();
问题:
1)如何从IQueryable对象推断实体类型2)我意识到我不能创建一个构造函数,它在创建静态时需要参数类。我是如何将映射器初始化为最佳/唯一的方式?
解决方案我试图用反射。约束仅限于演示。如果您想多次调用反射代码,请务必缓存最终的方法信息。
void Main()
{
var a = new Entity [] {new Entity {name =a},new Entity {name =b}};
Console.WriteLine(a.Take(1).Map< EntityDto>());
}
公共类实体
{
公共字符串名称;
}
public class EntityDto
{
public string dtoname;
}
public static class EntityExtensions
{
public static IEnumerable< U>映射< T,U>(这个IEnumerable< T> e)其中T:实体其中U:EntityDto,new()
{
foreach(var a in e)
{
yield返回新的U(){dtoname = a.name};
}
}
public static IEnumerable< U> Map< U>(此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>;
}
}
Currently we implement a mapping service like this (the service uses automapper, and we make use of the projection feature on it for this part)
// Injected
// IGenericRepository<Entity> entityRepo
var query = this.entityRepo
.FindAll(a => a.Id == someId)
.Take(1);
var result = this.mappingService
.Map<Entity, EntityDto>(query)
.FirstOrDefault();
I'd like to create an extension that would allow me to do the following
var result = this.entityRepo
.FindAll(a => a.Id == someId)
.Take(1).Map<EntityDto>() <--- Entity inferred from repo type
.FirstOrDefault();
My current attempt:
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);
}
}
Thus currently my implementation would look like this.
var result = this.entityRepo
.FindAll(a => a.Id == someId)
.Take(1).Map<Entity,EntityDto>()
.FirstOrDefault();
Questions:
1) How would i go about inferring the entity type from the IQueryable object
2) I realize i cant create a constructor that takes parameters, when creating a static class. Is the way i init the mapper the best/only way?
解决方案 I tried that with reflection. The constraints are only for demo. If you want to call the reflection code multiple times be sure to cache the final 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>;
}
}
这篇关于仿制药&静态类。实现查询帮助器方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!