Как избежать передачи ссылки на контейнер или использования CommonServiceLocator для EntityFactory - PullRequest
0 голосов
/ 29 ноября 2010

Мой класс Entity зависит от репозитория.

public class User
{
    private readonly IUserRepository _userRepository;

    public User(IUserRepository userRepository)
    {
        _userRepository = userRepository;
    }

    ...
}

И у меня есть класс EntityFactory, используемый репозиторием для создания сущностей.

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>());
    }
}

Есть ли способизбежать EntityFactory иметь ссылку на контейнер или использовать CommonServiceLocator?(Context Agnostic)

Или я просто неправильно проектирую свои классы, и класс User не должен зависеть ни от каких репозиториев?

Редактировать: Вот код, использующийметод от Давида:

// 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();
}

Ответы [ 2 ]

1 голос
/ 29 ноября 2010

Ваша структура DI должна предоставить вам метод создания фабрик:

public class EntityFactory
{
    public EntityFactory(Func<User> userFactory) { /* ... */ }

    public User InstantiateUser()
    {
        return userFactory.Invoke();
    }
}

Когда EntityFactory будет создан, он получит соответствующую фабрику User, которую затем можно будет использовать для правильного создания.разрешенные пользователи без каких-либо ссылок на IoC.

0 голосов
/ 29 ноября 2010

Что не так с вариантом 2 или 3?Если вы используете IoC или сервисный локатор, вам потребуется где-то ссылка на него.

У меня есть глобальная ссылка на контейнер IoC, и я использую ее для разрешения интерфейсов повсюду,Это выглядит как локатор службы, но вместо этого используется контейнер IoC.

Я не верю, что есть способ обойти это.

...