Unity Container ResolutionFailedException, когда отображение правильно в файле конфигурации - PullRequest
4 голосов
/ 13 сентября 2010

Я использовал ServiceLocator, который я умирал с Unity

public ServiceLocator(IUserStore userStore, IProdcutsStore productsStore, ...etc) {}

public IUserStore UserStore 
{ 
    get { return userStore; }
}

Все это работало нормально, но я хотел ленивую реализацию репозиториев, так как они довольно редко используются.

Так что мой ServiceLocator теперь выглядит как

    public ServiceLocator(IUnityContainer container) {}

    public IUserStore UserStore 
    { 
        get { return (IUserStore)container.Resolve(typeof(IUserStore)); }
    }

   //  ...etc

Теперь я получаю действительно бесполезную ошибку ResolutionFailedException

Не удалось разрешить зависимость, тип = "DomainModel.DataServices.Interface.IUserStore", name = "". Сообщение об исключении: текущая операция сборки (ключ сборки строить Клавиша [DomainModel.DataServices.Interface.IUserStore, null]) не удалось: текущий тип, DomainModel.DataServices.Interface.IUserStore, это интерфейс и не может быть построен. Вы пропустили тип отображение? (Тип стратегии BuildPlanStrategy, индекс 3)

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

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

Чего мне не хватает, что означает, что что-то где-то должно измениться, чтобы загружаться таким образом?

Обновление: Я предполагаю, что здесь происходит то, что, когда я добавляю контейнер в ServiceLocator, «основной» контейнер создает новый контейнер каждый раз, когда он не настроен должным образом. Я думаю, что, возможно, мне нужен какой-то способ указать, что я должен передать this в качестве контейнера, а не разрешить его с помощью нового экземпляра.

1 Ответ

3 голосов
/ 13 сентября 2010

Вы идете в несколько неправильном направлении ... Сначала у вас был тестируемый класс, который объявил свои зависимости в конструкторе, и вы превратили его в не тестируемый, запрашивая «что-то» внутри контейнера... Ничего хорошего = (

Вы должны либо внедрить некоторый фабричный интерфейс для вашего дорогого объекта и требовать его в конструкторе, либо (если можете) переключиться на Unity 2.0 и использовать Автоматические фабрики :

public ServiceLocator(Func<IUserStore> userStoreBuilder)

//...

public IUserStore UserStore 
{ 
   get { return userStoreBuilder(); }
}

Если вы хотите создать экземпляр этого объекта только один раз, вы можете добавить каскад к этому свойству, или с .NET 4.0 вы можете попробовать , спрашивая Lazy в конструкторе .

PS О, да. И отвечая на ваш конкретный вопрос =) Если вы все еще хотите внедрить экземпляр своего контейнера в другое место, вам необходимо сначала зарегистрировать его внутри себя =)

container.RegisterInstance<IUnityContainer>(container);

Исправление (см. Комментарии) НЕ регистрируйте контейнер Unity внутри себя, это вызовет StackOverflowException в container.Dispose(), коррЭкземпляр будет введен как зависимость без регистрации.

...