【问题标题】:Compose parts in MEF在 MEF 中编写零件
【发布时间】:2011-09-13 07:41:37
【问题描述】:

考虑以下情况:

[Export]
class A { }

class B 
{
  [Import]
  private A a;
}

// Instantiates class B.
class C 
{   
  public C(Type type){ /*Instantiate Class B here.*/}

  public void PerfomOperationUsingClassB() { }
}

class D
{
  void Initialize()
  {
    var catalog = new AssemblyCatalog(Assembly.GetAssembly(typeof(A)));
    var container = new CompositionContainer(catalog);

    // Is there any way to compose A with B?

    C c = new C(typeof(B));
    c.PerfomOperationUsingClassB();
  }
}

问题:我可以访问类“A”和“B”,但类“C”位于我无法修改的程序集中(因此无法修改类“C”)。有没有办法组成“A”和“B”?

【问题讨论】:

  • 啊!有代码格式化!清理 <br>  的混乱并不好玩。
  • 您想消除对 C 类的使用,还是强制调用 c.PerformOperationUsingClassB?
  • 现在可以用 MEF 导入私人会员吗?
  • 哦,酷!那我一定要试试新的东西!
  • @Matt New Bits? Mef 附带 .Net 4

标签: .net ioc-container mef composition


【解决方案1】:

不幸的是,如果无法访问 C 的构造函数正在执行的任何操作,那么您将非常不走运。 C 的构造函数似乎想使用类型本身来初始化 B 的实例......它是否提供任何机制来拦截 C 内的 B 的初始化?

如果C 接受B 的实例,您可以轻松地将B 的组合实例传递给构造函数。如果您想导出封闭类型C,您可以执行以下操作:

public class MefAdapter<T, TExport>
{
  private readonly Func<T, TExport> _factory = CreateFactory();
  private readonly T _arg;

  [ImportingConstructor]
  public MefAdapter(T arg)
  {
    _arg = arg;
  }

  [Export]
  public TExport Export
  {
    get { return _factory(_arg); }
  }

  internal static Func<T, TExport> CreateFactory()
  {
    var tArg = typeof(T);
    var tExport = typeof(TExport);

    var arg = Expression.Parameter(tArg, "arg");
    var ctor = tExport.GetConstructor(new[] { tArg });
    var ctorExp = Expression.New(ctor, arg);

    return Expression.Lamda<Func<T, TExport>>(ctorExp, arg).Compile();
  }
}

(本文基于Mark Seemann's Resolving closed types 文章)。

这样,C 应该看起来像:

public class C
{
  public C(B b)
  {

  }
}

您可以通过自动创建 B 来满足该封闭类型:

var typeCatalog = new TypeCatalog(typeof(MefAdapter<C>));
var catalog = new AggregateCatalog(new DirectoryCatalog("."), typeCatalog);

var container = new CompositionContainer(catalog);

var c = container.ComposeExportedValue<C>();
// This instance of C should have a composed instance of B injected.

【讨论】:

    【解决方案2】:

    我不这么认为,不是没有引用 B 的实例...

    如果您有参考资料,可以致电:

    container.SatisfyImportsOnce(instanceOfB);
    

    【讨论】:

      【解决方案3】:

      您可以像这样在class B 中使用ServiceLocator

      class B
      {
        private A a;
      
        B()
        {
          a = Microsoft.Practices.ServiceLocator.Current.GetInstance<A>();
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多