将 DTO 类型解析为 WCF 服务中的域类型
Resolve DTO type into Domain type in WCF service
我有一个 WCF 服务,它通过 net.tcp
与 SQL 到 EntityFramework 一起工作
允许客户端通过 Id 从 Db 查询项目。
我有很多方法,看起来像这样:
public SiteDTO GetSiteById(long siteId)
{
using (var context = new MyDbContext())
{
var site = context.Site.Find(siteId);
return AutoMapper.Mapper.Map<SiteDTO>(site);
}
}
所以我决定用一个方法来统治他们:
public TDTO GetEntityById<TDTO, TSet>(object id)
where TDTO : class
where TSet : class
{
using (var context = new MyDbContext())
{
var entity = context.Set<TSet>().Find(id);
if (entity == null)
return default(TDTO);
return AutoMapper.Mapper.Map<TSet, TDTO>(entity);
}
}
但问题是应该使用它的客户端对 TSet
类型一无所知(它是一种数据库类型,客户端仅适用于 DTO),因此不能以这种方式调用此方法。我需要这样做:
public TDTO GetEntityById<TDTO>(object id)
where TDTO : class
{
using (var context = new MyDbContext())
{
//Something like this and a lot of reflection...
Type setType = Resolver(typeof(TDTO));
//I know this won't work. Just to show my intentions
var entity = context.Set<setType>().Find(id);
if (entity == null)
return default(TDTO);
return AutoMapper.Mapper.Map<setType, TDTO>(entity);
}
}
我知道如何以可靠的方式解决问题 - 使 Dictionary<Type,Type>
注册一次并使用它。
问题:
有没有更优雅的方式(也许使用 AutoMapper 方法)来做到这一点?
如果您可以使用静态解析器,那么以下方法应该有效:
public static class DTOResolver
{
public static void RegisterSetForDTO<TSet, TDTO>()
where TDTO : class
where TSet : class
{
DTOResolver<TDTO>.SetType = typeof(TSet);
DTOResolver<TDTO>.SetMapper = new DTOResolver<TDTO>.Mapper<TSet>();
}
}
public static class DTOResolver<TDTO> where TDTO : class
{
public abstract class Mapper
{
public abstract TDTO Map(Object entity);
}
public class Mapper<TSet> : Mapper
{
public override TDTO Map(Object entity)
{
return AutoMapper.Mapper.Map<TSet, TDTO>((TSet) entity);
}
}
public static Type SetType { get; set; }
public static Mapper SetMapper { get; set; }
}
假设 DTO 和集合如下:
public class DTO1 {}
public class Set1 {}
public class DTO2 {}
public class Set2 {}
像这样注册您的映射:
static void Setup()
{
DTOResolver.RegisterSetForDTO<Set1, DTO1>();
DTOResolver.RegisterSetForDTO<Set2, DTO2>();
}
然后像这样修改你的GetEntityById
:
public TDTO GetEntityById<TDTO>(object id)
where TDTO : class
{
using (var context = new MyDbContext())
{
var entity = context.Set(DTOResolver<TDTO>.SetType).Find(id);
if (entity == null)
return default(TDTO);
return DTOResolver<TDTO>.SetMapper.Map(entity);
}
}
之所以可行,是因为 DTOResolver<TDTO>
在内存中定义了一个新的静态边界,特定于单个 TDTO
类型,使我们能够注册一个 Type
供 Set 使用对于那个 TDTO
和一个 Mapper
子类来实例化一个单例,因为它被输入到一个特定的 TSet
.
我有一个 WCF 服务,它通过 net.tcp
与 SQL 到 EntityFramework 一起工作允许客户端通过 Id 从 Db 查询项目。
我有很多方法,看起来像这样:
public SiteDTO GetSiteById(long siteId)
{
using (var context = new MyDbContext())
{
var site = context.Site.Find(siteId);
return AutoMapper.Mapper.Map<SiteDTO>(site);
}
}
所以我决定用一个方法来统治他们:
public TDTO GetEntityById<TDTO, TSet>(object id)
where TDTO : class
where TSet : class
{
using (var context = new MyDbContext())
{
var entity = context.Set<TSet>().Find(id);
if (entity == null)
return default(TDTO);
return AutoMapper.Mapper.Map<TSet, TDTO>(entity);
}
}
但问题是应该使用它的客户端对 TSet
类型一无所知(它是一种数据库类型,客户端仅适用于 DTO),因此不能以这种方式调用此方法。我需要这样做:
public TDTO GetEntityById<TDTO>(object id)
where TDTO : class
{
using (var context = new MyDbContext())
{
//Something like this and a lot of reflection...
Type setType = Resolver(typeof(TDTO));
//I know this won't work. Just to show my intentions
var entity = context.Set<setType>().Find(id);
if (entity == null)
return default(TDTO);
return AutoMapper.Mapper.Map<setType, TDTO>(entity);
}
}
我知道如何以可靠的方式解决问题 - 使 Dictionary<Type,Type>
注册一次并使用它。
问题: 有没有更优雅的方式(也许使用 AutoMapper 方法)来做到这一点?
如果您可以使用静态解析器,那么以下方法应该有效:
public static class DTOResolver
{
public static void RegisterSetForDTO<TSet, TDTO>()
where TDTO : class
where TSet : class
{
DTOResolver<TDTO>.SetType = typeof(TSet);
DTOResolver<TDTO>.SetMapper = new DTOResolver<TDTO>.Mapper<TSet>();
}
}
public static class DTOResolver<TDTO> where TDTO : class
{
public abstract class Mapper
{
public abstract TDTO Map(Object entity);
}
public class Mapper<TSet> : Mapper
{
public override TDTO Map(Object entity)
{
return AutoMapper.Mapper.Map<TSet, TDTO>((TSet) entity);
}
}
public static Type SetType { get; set; }
public static Mapper SetMapper { get; set; }
}
假设 DTO 和集合如下:
public class DTO1 {}
public class Set1 {}
public class DTO2 {}
public class Set2 {}
像这样注册您的映射:
static void Setup()
{
DTOResolver.RegisterSetForDTO<Set1, DTO1>();
DTOResolver.RegisterSetForDTO<Set2, DTO2>();
}
然后像这样修改你的GetEntityById
:
public TDTO GetEntityById<TDTO>(object id)
where TDTO : class
{
using (var context = new MyDbContext())
{
var entity = context.Set(DTOResolver<TDTO>.SetType).Find(id);
if (entity == null)
return default(TDTO);
return DTOResolver<TDTO>.SetMapper.Map(entity);
}
}
之所以可行,是因为 DTOResolver<TDTO>
在内存中定义了一个新的静态边界,特定于单个 TDTO
类型,使我们能够注册一个 Type
供 Set 使用对于那个 TDTO
和一个 Mapper
子类来实例化一个单例,因为它被输入到一个特定的 TSet
.