I've came across a dilemma which I think is worth discussing here.
I have a set of domain objects (you can also call them entities, if you like), which get some data from a separate DAL which is resolved with an IoC.
I was thinking about making my system very extensible, and I'm wandering if it is right to also resolve these entities by the IoC.
Let me present a dumb example.
Let's say I have a web site for which I have the following interface:
public interface IArticleData
{
int ID { get; }
string Text { get; set; }
}
The concept is, that the DAL implements such interfaces, and also a generic IDataProvider<TData>
inteface, after which the DAL becomes easily replaceable. And there is the following class, which uses it:
public class Article
{
private IArticleData Data { get; set; }
public int ID
{
get { return Data.ID; }
}
public int Text
{
get { return Data.Text; }
set { Data.Text = value; }
}
private Article(IArticleData data)
{
Data = data;
}
public static FindByID(int id)
{
IDataProvider<IArticleData> provider = IoC.Resolve<IDataProvider<IArticleData>>();
return new Article(provider.FindByID(id));
}
}
This makes the entire system independent of the actual DAL implementation (which would be in the example, IDataProvider<IArticleData>
).
Then imagine a situation in which this functionality is not really enough, and I'd like to extend it. In the above example, I don't have any options to do it, but if I make it implement an interface:
public interface IArticle
{
int 开发者_如何学JAVAID { get; }
string Text { get; set; }
}
public class Article : IArticle
{
...
}
And then, I remove all dependencies to the Article class and start resolving it as a transient IArticle component with an IoC.
For example, in Castle: <component id="ArticleEntity" service="IArticle" type="Article" lifestyle="transient" />
After this, if I have to extend it, that would be this simple:
public class MyArticle : Article
{
public string MyProperty { ..... }
}
And all I have to do is change the configuration to this: <component id="ArticleEntity" service="IArticle" type="Article" lifestyle="transient" />
So anyone who would use the system in question would be able to replace all classes as simply as rewriting a line in the configuration. All the other entities would work correctly also, because the new one would implement the same functionality as the old one.
By the way, this seems to be a good solution for the "separation of concerns" philosophy.
My question is, is this the right thing to do? After some serious thinking, I couldn't figure out any better way to do this. I also considered MEF, but it seems to be oriented to making plugins but not to replace or extend already complete parts of a system like this.
I read many SO questions (and also other sources) about the topic, the most notable are these: How should I handle my Entity/Domain Objects using IoC/Dependency Injection? and IoC, Where do you put the container?
And I'm also afraid that I'm falling to the problems described on the following pages: http://martinfowler.com/bliki/AnemicDomainModel.html and http://hendryluk.wordpress.com/2008/05/10/should-domain-entity-be-managed-by-ioc/
And one more thing: this would increase the testability of the entire system, isn't it?
What do you think?
EDIT:
Another option would be to create a Factory pattern for these entities, but IoC.Resolve<IArticle>
is way simpler than IoC.Resolve<IArticleFactory>().CreateInstance()
I think you may be overcomplicating things. Would you ever have a need to replace Article with another type that implemented IArticle?
IoC containers are best used when you have a higher-level component that depends on a lower-level component, and you want the higher-level component to depend on an abstraction of that component because the lower-level component performs some operations internally that make it difficult to test the higher-level component e.g. database access. Or the lower-level component might represent a particular strategy in your application that can be interchangeable with other strategies e.g. a database gateway that abstracts out the details of working with vendor-specific database APIs.
As Article is a simple, POCO-style class, it's unlikely that you would gain any benefits creating instances of it though an IoC container.
精彩评论