MEF - 我可以创建实例并自动将它们组合在MEF中吗?

时间:2010-12-14 15:54:26

标签: c# .net mef .net-4.0

据我了解,为了使导入/导出属性彼此正确连接,我必须为每个具有这些属性的新实例调用compositionContainerInstance.Compose(...)

是否有可能自动发生这种情况,所以每当我创建一些可组合类的新实例时,我都不必这样做?

这将是一个例子,尽管它很长,它抽象了我的问题。

public class Worker1
{
    [Import(typeof(IDataProvider))]
    public IDataProvider DataProvider;

    public Worker2 second;
    //use data provider to perform logic
}

public class Worker2
{
    [Import(typeof(IDataProvider))]
    public IDataProvider DataProvider;

    //use data provider to perform logic
}

[Export(typeof(IDataProvider))]
public class GeoDataProvider : IDataProvider
{
    //implements logic
}

public class Container
{
    private Worker1 t1;
    public void Init()
    {
        AggregateCatalog cat = new AggregateCatalog();
        cat.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
        cat.Catalogs.Add(new DirectoryCatalog("."));

        CompositionContainer c = new CompositionContainer(cat);
        c.ComposeParts(new GeoDataProvider(), this);
    }

    public void PerformLogic()
    {
        t1 = new Worker1;
        //here it fails because I need c.ComposeParts(t1):
        t1.DoSomethingWithProvider();
        //but even if I do c.ComposeParts(t1), still the t1.second.DataProvider will be null
        //how to avoid this?
    }
}

我希望能够自由创建Worker1 / Worker2的新实例,而无需知道必须在使用前编写它们。那可行吗?

1 个答案:

答案 0 :(得分:4)

有人必须知道他们需要写作。

如果您要自由创建Worker1和Work2实例而不是让MEF创建它们,那么您还必须让MEF有机会满足新实例的导入,或者如您所发现的那样,IDataProvider字段永远不会被填充进行。

这是一个让MEF根据需要创建类的示例。只需要一次“ComposeParts”调用即可完成所有设置。

[Export]
public class Worker1
{
  [Import]
  public IDataProvider DataProvider;

  [Import]
  public Worker2 second;

  //use data provider to perform logic
  public void DoSomethingWithProvider() {
    }
}

[Export]
public class Worker2
{
  [Import]
  public IDataProvider DataProvider;

  //use data provider to perform logic
}

[Export( typeof( IDataProvider ) )]
public class GeoDataProvider : IDataProvider
{
  //implements logic
}

public class Container
{
  [Import]
  private Worker1 t1;

  public void Init()
  {
    AggregateCatalog cat = new AggregateCatalog();
    cat.Catalogs.Add( new AssemblyCatalog( Assembly.GetExecutingAssembly() ) );
    cat.Catalogs.Add( new DirectoryCatalog( "." ) );

    CompositionContainer c = new CompositionContainer( cat );
    c.ComposeParts( this );
  }

  public void PerformLogic()
  {
    t1.DoSomethingWithProvider();
  }
}