在WCF服务中将DTO类型解析为域类型

本文关键字:类型 DTO WCF 服务 | 更新日期: 2023-09-27 18:04:24

我有一个WCF服务,它通过net.tcp通过EntityFramework与SQL一起工作

允许客户端根据Db的Id查询项目。

我有很多像这样的方法:

    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方法)来做到这一点?

在WCF服务中将DTO类型解析为域类型

如果您同意使用静态解析器,那么以下内容应该可以工作:

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和set是这样的:

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,用于该TDTO和单个Mapper子类,以实例化一个类型为特定TSet的单例。