How do I use a Type Discriminator field in my DTO to instantiate the appropriate domain object with DI?
I am looking for suggestions on how to map a single DTO class with a type discriminator to multiple domain classes.
I have my DTO:
public class FooData
{
public Guid Id { get; set; }
public string Name { get; set; }
public string T开发者_StackOverflow社区ypeDiscrim { get; set; }
}
public class FooDataRepository
{
public List<FooData> GetAll() { /* select * from foo, basically */ }
}
I have a base domain object with a constructor dependency on a repository with a generic parameter:
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();
}
Then I have a sample inheritor from my base domain object:
// 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 { }
Now here's the kicker: I have a class that will consume a list of IFooDomain, which it gets from a repository. (IFooDomain is necessary because of the type parameter in FooDomainBase.)
// 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
}
}
}
Can I get the behavior in the comments above done with a DI framework? I'm guessing that I have to as the Service Locator pattern to return me an instantiated FooDomainBase
inheritor, but I also need the constructor parameter of IBarRepository<SuperBar>
resolved.
What frameworks can handle this sort of thing? If not out of the box, what do I need to extend?
I'm also open to critiques of the object hierarchy, since this may be pointing to a flaw in the design above.
I'm not sure I was able to follow all the Foo/Bar stuff, but the standard solution to this kind of problem is by injecting one or more Abstract Factories into the consumer in question.
Define:
public interface IFooDomainFactory
{
IFooDomain Create(string discriminator);
}
an inject it into FooRepository. When you implement IFooDomainFactory, you will need a way to get an IBarRepository<SuperBar>
, but you can now define a new Abstract Factory that gives you that and inject it into the concrete FooDomainFactory.
You don't need any particular DI Container to do this, but they are all able to resolve dependencies like that.
Don't use Service Locator - it's an anti-pattern.
精彩评论