如何在DTO中使用Type Discriminator字段使用DI实例化相应的域对象?

时间:2010-02-11 17:20:30

标签: .net dependency-injection ioc-container

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

我有我的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中的类型参数,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 个答案:

答案 0 :(得分:1)

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

定义:

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

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

您不需要任何特定的DI容器来执行此操作,但它们都能够解决此类依赖关系。

请勿使用服务定位器 - it's an anti-pattern