代码之家  ›  专栏  ›  技术社区  ›  Josh Kodroff

如何在DTO中使用类型鉴别器字段用DI实例化适当的域对象?

  •  1
  • Josh Kodroff  · 技术社区  · 16 年前

    我正在寻找如何将一个带有类型鉴别器的DTO类映射到多个域类的建议。

    public class FooData
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public string TypeDiscrim { get; set; }
    }
    
    public class FooDataRepository
    {
        public List<FooData> GetAll() { /* select * from foo, basically */ }
    }
    

    我有一个基域对象,它的构造函数依赖于一个具有泛型参数的存储库:

    public interface IFooDomain {}
    
    public class FooDomainBase<B1> : IFooDomain where B1 : BarBase
    {
        protected IBarRepository<B1> _barRepository;
    
        public FooDomainBase(FooData data, IBarRepository<B1> barRepository)
        {
            Id = data.Id;
            Name = data.Name;
            _barRepository = barRepository;
        }
    
        public virtual void Behavior1()
        {
            B1 thingToDoStuffWith = _barRepository.GetBar();
            /* do stuff */
        }
    
        public Guid Id { get; set; }
        public string Name { get; set; }
    }
    
    public class BarBase {}    
    
    public interface IBarRepository<B1> where B1 : BarBase
    {
        B1 GetBar();
    }
    

    然后,我有一个来自基本域对象的示例继承器:

    // There will be several of these
    public class SuperFooDomain1 : FooDomainBase<SuperBar>
    {
        public SuperFooDomain1(FooData data, IBarRepository<SuperBar> barRepository) : base(data, barRepository)
        { }
    
        public override void  Behavior1() { /* do something different than FooDomainBase */ }
    }
    
    public class SuperBar : BarBase { }
    

    现在关键是:我有一个类将使用IFooDomain列表,它从存储库中获取。(由于FooDomainBase中的type参数,IFooDomain是必需的。)

    // The FooManager class (not pictured) will use this to get all the 
    public class FooRepository
    {
        private FooDataRepository _datarepository;
    
        public FooRepository(FooDataRepository dataRepository)
        {
            _datarepository = dataRepository;
        }
    
        public List<IFooDomain> GetAll()
        {
            foreach (var data in _datarepository.GetAll())
            {
                // Convert FooData into appropriate FooDomainBase inheritor
                // depending on value of FooData.TypeDiscrim
            }
        }
    
    }
    

    我能用DI框架完成上面评论中的行为吗?我猜我必须作为服务定位器模式返回一个实例化的 FooDomainBase 继承器,但我还需要 IBarRepository<SuperBar> 断然的。

    什么样的框架可以处理这种事情?如果不是开箱即用,我需要扩展什么?

    我也对对象层次结构的批评持开放态度,因为这可能指向了上述设计中的一个缺陷。

    1 回复  |  直到 16 年前
        1
  •  1
  •   Mark Seemann    16 年前

    我不确定我是否能够遵循Foo/Bar的所有内容,但这类问题的标准解决方案是注入一个或多个 抽象工厂 对消费者提出质疑。

    定义:

    public interface IFooDomainFactory
    {
        IFooDomain Create(string discriminator);
    }
    

    把它注入到FooRepository中。当您实现IFooDomainFactory时,您需要一种方法来获得 IBarRepository<SuperBar> ,但现在您可以定义一个新的抽象工厂,它提供给您,并将它注入具体的FooDomainFactory中。

    您不需要任何特定的DI容器来完成这项工作,但是它们都能够像那样解析依赖关系。

    it's an anti-pattern .

    推荐文章