I have the following interface defined
IOne
ITwo
IThree
ICalcalculator
And have several implementations of them
ClassOne: IOne
ClassTwo: IOne
ClassThree : ITwo
ClassFour : ITwo
ClassFive: IThree
MyCalc : ICalculator
MyCalc requires classes 1-4, however 2 instances of ClassOne
and ClassThree
differentiated as initialization ie
public MyCalc(){
ClassOne first= new ClassOne("filePath1");
ClassOne second = new ClassOne("filePath2");
ClassThree third = new ClassThree ("filePath3");
ClassThree fourth = new ClassThree ("filePath4");
}
I am trying to use MEF to create construct MyCalc. In the above example, the filePathX
will be in a configuration file. I have done the following thus far and it seems to work, however my feeling is that my current method and approach is not correct. Looking at this approach, I have bound myself with names (ValDatePrices & EDDatePrices) and it is no cleaner than my current approach(see above).
Is there a cleaner way to load several objects of the same type with different ctor arguments?
public class MyCalc: ICalculator
{
private CompositionContainer container;
public MyCalc()
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(typeof(MyCalc).Assembly));
container = new CompositionContainer(catalog);
try
{
this.container.ComposeExportedValue<ClassFive>(
new ClassFive((ConfigurationManager.AppSettings["SomePath"])));
this.container.ComposeExportedValue<ClassOne>(
"ValDatePrices"
, new ClassOne((ConfigurationManager.AppSettings["filePath1"])));
this.container.ComposeExportedValue<ClassOne>(
"EDDatePrices"
, new ClassOne((ConfigurationManager.AppSettings["filePath2"])));
this.container.ComposeParts(this);
}
catch (CompositionException compositionException)
{
Console.WriteLine(compositionException.ToString());
}
}
[Import("ValDatePrices")]
public ClassOne ValDatePrices;
[Import("EDDatePrices")]
public ClassOne EDDatePrices;
[Import]
public ClassFive SPointReader;
public void Calculate()
{
Console.WriteLine(SPointReader.Result);
Console.WriteLine(ValDatePrices.Result.Count);
Console.WriteLine(EDDatePrices.Result.Count);
Console.ReadKey();
}
}
Usage
class Program
{
static void Main(string[] args)
{
var p = new MyCalc();
p.Calculate();
}
}
}
Side question: where should the code in the MyCalc
constructor be located?
Have you considered using a proper DI/IoC container? This can be easily achieved in a clean way using eg NInject or StructureMap .
Here is an example of how this can be implemented with NInject. Note that there are numerous ways of doing this, you should look at their tutorial to get NInject to suit you needs.
MyCalculator
public class MyCalculator : ICalculator
{
private IOne _oneFirst;
private IOne _oneSecond;
private ITwo _twoFirst;
private ITwo _twoSecond;
private IThree _three;
public MyCalculator([Named("Val")] IOne oneFirst, [Named("ED")] IOne oneSecond,
[Named("Val")] ITwo twoFirst, [Named("ED")] ITwo twoSecond, IThree three)
{
_oneFirst = oneFirst;
_oneSecond = oneSecond;
_twoFirst = twoFirst;
_twoSecond = twoSecond;
_three = three;
}
public void Calculate()
{
}
}
Kernel
public class CalculatorModule : NinjectModule
{
public override void Load()
{
Bind<IOne>().ToMethod(CreateOne).Named("Val");
Bind<IOne>().ToMethod(CreateTwo).Named("ED");
Bind<ITwo>().ToMethod(CreateThree).Named("Val");
Bind<ITwo>().ToMethod(CreateFour).Named("ED");
Bind<IThree>().To<ClassFive>();
Bind<ICalculator>().To<MyCalculator>();
}
private ITwo CreateFour(IContext arg)
{
return new ClassFour();
}
private ITwo CreateThree(IContext arg)
{
return new ClassThree();
}
private IOne CreateOne(IContext context)
{
return new ClassOne("filePath1");
}
private IOne CreateTwo(IContext arg)
{
return new ClassTwo("filePath2");
}
}
Note about kernel: The methods can be shortened to lambda functions if you like and the named attributes can be replaced by parameter names or custom attributes. See Contextual Binding
Usage
class Program
{
static void Main(string[] args)
{
StandardKernel kernel = new StandardKernel(new CalculatorModule());
var cal = kernel.Get<ICalculator>();
cal.Calculate();
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.