Регистрация общего абстрактного класса в Castle Windsor

#c# #inversion-of-control #castle-windsor

#c# #инверсия контроля #castle-windsor

Вопрос:

Я пытаюсь зарегистрировать тип по соглашению, я упростил свой случай в этом примере:

 public abstract class BaseEntity{}

public class EntityA : BaseEntity{}

public class EntityB : BaseEntity{}

public abstract class BaseClass
{
    //...
}

public abstract class GenericBaseClass<T> : BaseClass where T : BaseEntity
{
    //..
}

public class ConcreteA : GenericBaseClass<EntityA>
{
    //...
}

public class ConcreteB : GenericBaseClass<EntityB>
{
    //...
}
 

Я пытаюсь найти способ зарегистрироваться GenericBaseClass , чтобы вернуться ConcreteA при запросе GenericBaseClass<EntityA> . При попытке решить эту проблему я получаю исключение, в котором говорится что-то вроде:

Ошибка активации произошла при попытке получить экземпляр типа GenericBaseClass`1, ключ «»

Если я изменю определение GenericBaseClass<T> с абстрактного класса на интерфейс, этот регистрационный код будет работать:

 container.Register(AllTypes.FromAssemblyContaining<BaseClass>()
         .BasedOn(typeof(GenericBaseClass<>))
         .WithService.FirstInterface());
 

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

Я пробовал с этим:

 container.Register(AllTypes.FromAssemblyContaining<BaseClass>()
         .BasedOn(typeof(GenericBaseClass<>))
         .WithService.Base());
 

Отлаживая, я вижу, что тип не добавлен в контейнер.

Я использую Castle Windsor 2.6.

Спасибо.

Комментарии:

1. Нет Windsor 2.6. Вы имели в виду 2.5.4?

Ответ №1:

Это работает:

 container.Register(AllTypes.FromAssemblyContaining<ConcreteA>()
                    .BasedOn(typeof (GenericBaseClass<>))
                    .WithService.Base());
 

Если вы видите, что типы не добавляются в контейнер, убедитесь, что вы просматриваете правильную сборку (ту, которая содержит типы реализации, а не типы сервисов).

Комментарии:

1. Не удалось заставить его работать так, как вы предлагали. Это сработало, но мне пришлось добавить тот же код для любого типа ConcreteX: container . Регистр(Компонент. Для(typeof(GenericBaseClass<EntityA>)) .ImplementedBy(typeof(ConcreteA)) .Named(«ConcreteA») );

2. Почему бы и нет? Это именно то, что делает мой код (за исключением части имени)

3. @Hero, твое решение сработало для меня, у меня есть один абстрактный базовый класс и 2 реализации. У меня уже был тот же код, но не хватало . Именованная («…») часть для разграничения регистраций обоих компонентов с использованием одного и того же сервиса. Спасибо!

4. @Hero вы должны ответить на свой вопрос и проголосовать за него, чтобы все знали об этом.