Внедрение зависимостей со статическими классами и свойствами

Я разработал многоуровневое решение и создал несколько классов Manager для реализации бизнес-логики. Все менеджеры являются производными от класса BaseManager. Чтобы было понятнее, вот класс UserManager:

public class UserManager : BaseManager
{
    public void Add(User user)
    {
       ...
    }
    public void Update(User user)
    {
       ...
    }
    public void Delete(User user)
    {
       ...
    }
    public bool GetAccessPermissions(User user)
    {
       ...
    }
}  

BaseManager выглядит следующим образом:

public class BaseManager
{  
    protected IRepository repository = IoCLocator.Resolve<IRepository>();
    public BaseManager()
    {
        ...
    }
    // Some shared methods among manager classes.
}  

Теперь я скептически отношусь к тому, чтобы все мои классы менеджеров были определены статически, поскольку они получают свои связанные объекты, с которыми они хотят работать, в качестве параметров. Но, как вы видите, у меня есть несколько общих частных/защищенных членов, которые я должен создавать при каждом вызове. (например, repository должен создаваться при создании каждого класса менеджера).

Каков мой выбор, чтобы определить классы менеджеров как статические и по-прежнему создавать экземпляры защищенных членов при каждом вызове методов менеджеров?


person Kamyar    schedule 14.09.2011    source источник


Ответы (2)


Вам нужно, чтобы ваши классы менеджеров были статическими, или вы просто хотите, чтобы они были синглтонами?

Вы ищете способ иметь одноэлементный класс с временными зависимостями?

В этом случае я бы ответил, что класс менеджера синглтона должен зависеть от фабрики, которая может создавать экземпляры репозиториев по мере необходимости.

Windsor предлагает типизированную фабрику, которая помогает создавать такие фабрики: http://docs.castleproject.org/Windsor.Typed-Factory-Facility-interface-based-factories.ashx

person Ian Nelson    schedule 14.09.2011

Здесь у вас есть несколько вариантов:

1)

 public class BaseManager
    {  
        protected IRepository repository;
        public BaseManager(IRepository _repository)
        {
            repository = _repository 
        }
        // Some shared methods among manager classes.
    }  

Это требует, чтобы вы создали экземпляр вашего BaseManager, используя

IoCLocator.Resolve<BaseManager>();

или что-то в этом роде, в зависимости от конкретного IoCLocator (MEF, Unity, Ninject или что вы используете)

2) Примерно так же:

 public class BaseManager
     {  
        protected IRepository repository;
        public BaseManager(IoCLocator locator)
        {
            repository = locator.Resolve<IRepository>();
        }
        // Some shared methods among manager classes.
     } 

3) Или введите свойство напрямую

 public class BaseManager
 {  
    [InjectFromContainer]
    protected IRepository repository {get;set;}

    public BaseManager()
    {
        repository = locator.Resolve<IRepository>();
    }
    // Some shared methods among manager classes.
 }  

Я не могу точно назвать нужный вам Атрибут, потому что это зависит от вашего контейнера. В любом случае вам придется создать экземпляр контейнера IoC в BootStrapper, зарегистрировать в нем BaseManager, а затем разрешить его экземпляр из контейнера.

Надеюсь, это поможет, Илья

ОБНОВЛЕНИЕ:

Твоя концепция просто лажа. Статические классы, которые вы хотите наследовать, контейнер IoC, работающий с основными классами приложения, является статическим. Я бы порекомендовал вам выбрать по одному из каждого, и проблема исчезнет сама собой.

person Ilya Smagin    schedule 14.09.2011
comment
Думаю, я недостаточно ясно выразился. Здесь я пытаюсь добиться статического определения менеджеров (BaseManager и UserManager) и иметь доступ к статической переменной репозитория с помощью IoC, экземпляр которого создается при каждом вызове. - person Kamyar; 14.09.2011
comment
если ваши репозитории статичны? какая польза от защищенного? - person Ilya Smagin; 14.09.2011
comment
Я использовал защищенный, чтобы член репозитория был виден всем дочерним классам (например, UserManager). Репозитории не должны определяться для каждого вызова. - person Kamyar; 14.09.2011
comment
Спасибо. Немного изучив, я должен признать, что концепция была действительно беспорядком и проблемой шаблона проектирования. - person Kamyar; 14.09.2011