将 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.