Многократная инъекция интерфейса с замком Виндзор - PullRequest
8 голосов
/ 24 ноября 2008

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

Например, допустим, у меня есть простой интерфейс под названием IExamCalc, который выполняет вычисления, чтобы понять, как кто-то сделал на этом экзамене.

Нет, у нас есть несколько реализаций, таких как ниже, например,

public interface IExamCalc
{
    int CalculateMark(ExamAnswers examAnswers)
}

public class WritenExam : IExamCalc
{
    public int CalculateMark(ExamAnswers examAnswers)
    {
         return 4;
    }
}

public class OralExam : IExamCalc
{
    public int CalculateMark(ExamAnswers examAnswers)
    {
         return 8;
    }
}

public class ExamMarkService
{
    private IExamCalc _examCalc;
    public ExamMarkService(IExamCalc examCalc)
    {
        _examCalc = examCalc;
    }

    public int[] CalculateExamMarks(ExamAnswers[] examAnswers)
    {
        IList<int> marks = new List<int>;
        foreach(ExamAnswers examanswer in examaAnswers)
        {
            marks.Add(_examCalc.CalculateMark);
        }
    }
}

Скажите, что ExamMarkService восстанавливается через Windor. Как я могу убедиться, что в конструктор введена правильная реализация, и является ли это примером проблемы с несколькими арендаторами?

Надеюсь, что все имеет смысл

Колин Г

Ответы [ 3 ]

12 голосов
/ 26 ноября 2008

Как сказал Дэвид, вы не можете, но IHandlerSelector позволит вам взять управление на себя. Посмотрите тесты, чтобы понять, как их использовать: https://svn.castleproject.org/svn/castle/trunk/InversionOfControl/Castle.Windsor.Tests/HandlerSelectorsTestCase.cs

По сути, вы бы сделали что-то вроде:

public class WritenExamHandler : IHandlerSelector
    {
        public bool HasOpinionAbout(string key, Type service)
        {
            // Decision logic here
            return somethingThatWouldBeTrueToSelectWritenExam && service == typeof(IExamCalc);
        }

        public IHandler SelectHandler(string key, Type service, IHandler[] handlers)
        {
            return handlers.Where(handler => handler.ComponentModel.Implementation == typeof (WritenExam)).First();
        }
    }

и затем вы регистрируете его с помощью:

container.Kernel.AddHandlerSelector(new WritenExamHandler());

Это позволит вам легко справляться с мультитенансными проблемами:)

3 голосов
/ 24 ноября 2008

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

Все ваши компоненты имеют ключи, которые являются уникальными строками, поэтому вы всегда можете container.Resolve("someKey") получить конкретную реализацию.

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

<component id="someService.customer1" service="ISomeService" type="Customer1SomeService" />

<component id="anotherId" service="IAnotherService" type="AnotherService">
    <parameters>
        <parameterName> <!-- as written in the ctor's signature -->
           ${someService.customer1}
        </parameterName>
    </parameters> 
</component>
1 голос
/ 24 ноября 2008

Короткий ответ: нельзя. Этот тип выбора зависит от кода приложения, поэтому, если вы только что сделали container.Resolve<IExamCalc>, то Виндзор не мог знать, какой именно вам нужен.

Вопрос, который нужно задать: как вы знаете, какой тип использовать?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...