How can you get castle Windsor to choose the right implantation of a interface at run time when you have multiple implementations in the container.
For example lets say i have a simple interface called IExamCalc that does calculations to work out how someone did in that exam.
No we have several implementation of this like bellow for example,
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);
}
}
}
Say the ExamMarkService is being resloved through Windor how can i make sure that the correct implementation is injected in the constructor and is this an example of a multi-tenancy problem?
Hope that all makes sence
Colin G
As David said, you can't, but IHandlerSelector will let you take control. Check out the tests to get an idea of how to use them: https://svn.castleproject.org/svn/castle/trunk/InversionOfControl/Castle.Windsor.Tests/HandlerSelectorsTestCase.cs
Basically, you would do something like:
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();
}
}
and then you register it with:
container.Kernel.AddHandlerSelector(new WritenExamHandler());
This will allow you to easily deal with multi-tenency issues :)
Multi-tenancy is defined as being able to run your software on one instance, serving multiple tenants/customers/clients. I guess you could run into problems like yours more often in a multi-tenancy setup.
All your components have keys which are unique strings, so you may always so a container.Resolve("someKey")
to get a specific implementation.
If you want to have a specific implementation automatically injected, you may configure your component like this (off my memory, may not be 100% precise):
<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>
The short answer is, you can't. This kind of choice is dependent on application code, so if you just did container.Resolve<IExamCalc>
, then Windsor couldn't know which one you wanted.
The question to ask is how do you know which type to use?