我可以使用MEF来组合具有不同构造函数参数的同一类型的几个项吗

本文关键字:类型 几个 构造函数 MEF 可以使 组合 我可以 参数 | 更新日期: 2023-09-27 18:21:27

我有以下接口定义的

  • IOne
  • ITwo
  • IThree
  • ICalcalculator

并且有几个的实现

  • ClassOne: IOne
  • ClassTwo: IOne
  • ClassThree : ITwo
  • ClassFour : ITwo
  • ClassFive: IThree
  • MyCalc : ICalculator

MyCalc需要类1-4,但是ClassOneClassThree的2个实例区别为初始化,即

public MyCalc(){
    ClassOne first= new ClassOne("filePath1");
    ClassOne second = new ClassOne("filePath2");
    ClassThree third = new ClassThree ("filePath3");
    ClassThree fourth = new ClassThree ("filePath4");
}

我正在尝试使用MEF来创建构造MyCalc。在上面的示例中,filePathX将位于配置文件中。到目前为止,我已经做了以下几项工作,似乎奏效了,但我觉得我目前的方法和方法是不正确的。考虑到这种方法,我将自己与名称(ValDatePrices和EDDatePrices)绑定在一起,它并不比我目前的方法更干净(见上文)。

有没有一种更干净的方法来加载具有不同ctor参数的同一类型的多个对象?

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(); 
    }
}

用法

class Program
{
    static void Main(string[] args)
    {
        var p = new MyCalc();
        p.Calculate();
    }
}
}

附带问题:MyCalc构造函数中的代码应该位于哪里

我可以使用MEF来组合具有不同构造函数参数的同一类型的几个项吗

您是否考虑过使用合适的DI/IoC容器?这可以通过使用例如NInject或StructureMap以干净的方式轻松实现。

以下是如何使用NInject。注意,有很多方法可以做到这一点,你应该看看他们的教程,让NInject适合你的需要。

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()
    {
    }
}

内核

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");
    }

}

关于内核的注意:如果您愿意,可以将方法缩短为lambda函数,并且可以用参数名称或自定义属性替换命名属性。参见上下文绑定

用法

class Program
{
    static void Main(string[] args)
    {
        StandardKernel kernel = new StandardKernel(new CalculatorModule());
        var cal = kernel.Get<ICalculator>();
        cal.Calculate();
    }
}