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

时间:2015-07-23 06:56:28

标签: c# entity-framework generics automapper parametric-namespaces

我有一个WCF服务,通过net.tcp

通过EntityFramework与SQL一起工作

允许客户通过ID从Db查询项目。

我有很多方法,如下所示:

    public SiteDTO GetSiteById(long siteId)
    {
        using (var context = new MyDbContext())
        {
            var site = context.Site.Find(siteId);
            return AutoMapper.Mapper.Map<SiteDTO>(site);
        }
    }

所以我决定制作The One Method来统治它们:

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

1 个答案:

答案 0 :(得分:1)

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

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类型,使我们能够为要使用的Set注册单个Type TDTO和单个Mapper子类来实例化单例,并将其键入特定的TSet