How to implement IoC in a Hierarchical Class
I have a hierarchical category list with Category obj开发者_运维技巧ects
public class Category
{
private int? ParentId = -1;
private Category _Parent = null;
public Category Parent
{
get
{
if (_Parent != null)
{
return _Parent;
}
if (this.ParentId.HasValue)
{
ICategoryRepository repo = new CategoryRepository();
var data = repo.Get(this.ParentId.Value);
_Parent = data;
}
return _Parent;
}
set
{
_Parent = null;
if (value == null)
{
ParentId = null;
}
else
{
ParentId = value.Id;
}
}
}
Each category has a Parent property which lazy loads its parent category.
The original category is loaded using an IRepository interface so i never have to new up a new instance of a repository within the business layer, they are provide at the application level via Dependency injection using Unity, ninject etc.
But here i see an instance when i need to create an instance of a repository from within the business layer. How would i change this design?
You might find using a Lazy<T> approach useful as explained here. This sets out quite a nice approach to allowing lazy loading whilst keeping persistence out of the business object class.
Move 'repo' to be a private member on the Category class. Set it's value through dependency injection (don't new it up inside the getter). Ensure that your IRepository.Get method works with your dependency injection framework to create the objects that it returns (so that 'repo' will be set in this case).
Interesting question. How about something like this:
public class Category
{
public int? ParentID{get;set;}
}
public class CategoryRepository
{
public Category Get(int id)
{
Category result = GetFromDBAlongWithParentID(id);
}
public Category GetParent(Category child)
{
return child.ParentID.HasValue ? (Category)null : this.Get(child.ParentID.Value);
}
}
Yes, the Category itself can't actually get it's own parent, and that does suck. But it does seem that where you're retrieving your original Category, you have access to the repository, so just continue using the repository when you need to get the parent object.
Robert Levy's answer is what immediately comes to mind, after having read your question. If you don't want to create hard dependency on the DI framework from your business layer, you may make the repository a property of the Category object and set this property when you created the repository object in the repo.Get. This feels quite yucky though as you don't necessarily need this reference (if you never lazy load) and also it is "hard coded" i.e not using DI as such. As an alternate you can use deferred resolution as described here http://msdn.microsoft.com/en-us/library/ff660854%28PandP.20%29.aspx This way, when you create a Category object you also get a resolver delegate, that the Category object will be able to call should it need to resolve a repository instance.
精彩评论