How to avoid passing a reference to the container or using CommonServiceLocator for an EntityFactory
开发者_JAVA技巧My Entity class has a dependency on a Repository.
public class User
{
private readonly IUserRepository _userRepository;
public User(IUserRepository userRepository)
{
_userRepository = userRepository;
}
...
}
And I have an EntityFactory class used by the Repository to create entities.
public class UserRepository : IUserRepository
{
private readonly EntityFactory _entityFactory;
public UserRepository(EntityFactory entityFactory)
{
_entityFactory = entityFactory;
}
...
}
// EntityFactory #1 with no references or dependencies to DI frameworks or CommonServiceLocator
public class EntityFactory
{
public User InstantiateUser()
{
return new User(); // Requires IUserRepository parameter
}
}
// EntityFactory #2 with reference to Ninject
using Ninject;
public class EntityFactory
{
private readonly IKernel _kernel;
public EntityFactory(IKernel kernel)
{
_kernel = kernel;
}
public User InstantiateUser(IKernel kernel)
{
return new User(_kernel.Get<IUserRepository>());
}
}
// EntityFactory #3 with reference to CommonServiceLocator
using Microsoft.Practices.ServiceLocation;
public class EntityFactory
{
public User InstantiateUser()
{
return new User(ServiceLocator.Current.GetInstance<IUserRepository>());
}
}
Is there a way to avoid the EntityFactory having a reference to the container or using the CommonServiceLocator? (Context Agnostic)
Or am I just designing my classes wrong and the User class should not have a dependency on any Repositories?
Edit: Here is the code using the method from David:
// Ninject binding
Bind<Func<User>>().ToMethod(cxt => () => new User(cxt.Kernel.Get<IUserRepository>()));
// EntityFactory class
private readonly Func<User> _userFactory;
public EntityFactory(Func<User> userFactory)
{
_userFactory = userFactory;
}
public User InstantiateUser()
{
return userFactory.Invoke();
}
Your DI framework should provide you with a method of creating factories:
public class EntityFactory
{
public EntityFactory(Func<User> userFactory) { /* ... */ }
public User InstantiateUser()
{
return userFactory.Invoke();
}
}
When the EntityFactory
is created it'll receive a proper User
factory which can then be used to create properly resolved users without any reference to the IoC.
What's wrong with option 2 or 3? If you are using IoC or a service locator, you will need to have a reference to it somewhere.
I have a global reference to the IoC container and use that to resolve the interfaces all over the place. This looks a lot like the service locator, but then instead using the IoC container.
I don't believe there is a way around this.
精彩评论