如何从MEF的多个零件中导入特定零件? [英] How to import specific part from multi parts in MEF?

查看:110
本文介绍了如何从MEF的多个零件中导入特定零件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将MEF用作DI容器,问题是我想从多个零件中导入特定零件.

I am using MEF as DI container and the problem is that I want to import specific part from multiple parts.

例如,我有以下代码:

public interface IService
{
    void Send();
}

[Export(typeof(IService))]
public class Service : IService
{
    public void Send()
    {
        Console.WriteLine("Service.Send");
    }
}

[Export(typeof(IService))]
public class FakeService : IService
{
    public void Send()
    {
        Console.WriteLine("FakeService.Send");
    }
}

[Import]
public IService Service { get; set; } // ---> let's say I want to use FakeService

有什么解决办法吗?

预先感谢

推荐答案

您可以将类中的元数据导出,下面是一个示例:

You can export metadata with your class, here's an example:

public interface ILogger
{
  void Log(string message);
}

[Export(typeof(ILogger)), ExportMetadata("Name", "Console")]
public class ConsoleLogger : ILogger
{
  public void Log(string message)
  {
    Console.WriteLine(message);
  }
}

[Export(typeof(ILogger)), ExportMetadata("Name", "Debug")]
public class DebugLogger : ILogger
{
  public void Log(string message)
  {
    Debug.Print(message);
  }
}

鉴于该合同和这些示例实现,我们可以将类型导入为Lazy<T, TMetadata>,从而可以定义元数据合同:

Given that contract and those example implementations, we can import out types as Lazy<T, TMetadata> whereby we can define a metadata contract:

public interface INamedMetadata
{
  string Name { get; }
}

您不必担心创建元数据的实现,因为MEF会将任何ExportMetadata属性值投影为TMetadata的具体实现,在我们的示例中为INamedMetadata.有了以上内容,我可以创建以下示例:

You don't need to worry about creating an implementation of the metadata, as MEF will project any ExportMetadata attribute values as concrete implementation of TMetadata, which in our example is INamedMetadata. With the above, I can create the following example:

public class Logger
{
  [ImportMany]
  public IEnumerable<Lazy<ILogger, INamedMetadata>> Loggers { get; set; }

  public void Log(string name, string message)
  {
    var logger = GetLogger(name);
    if (logger == null)
      throw new ArgumentException("No logger exists with name = " + name);

    logger.Log(message);
  }

  private ILogger GetLogger(string name)
  {
    return Loggers
      .Where(l => l.Metadata.Name.Equals(name))
      .Select(l => l.Value)
      .FirstOrDefault();
  }
}

在该示例类中,我将导入许多实例,例如Lazy<ILogger, INamedMetadata>实例.使用Lazy<T,TMetadata>允许我们在访问值之前访问元数据.在上面的示例中,我使用name参数选择要使用的适当记录器.

In that sample class, I am importing many instances, as Lazy<ILogger, INamedMetadata> instances. Using Lazy<T,TMetadata> allows us to access the metadata before accessing the value. In the example above, I'm using the name argument to select the appropriate logger to use.

如果在导入时实例化类是不合适的,则可以使用ExportFactory<T,TMetadata>,它允许您按需启动类型实例. (ExportFactory包含在.NET 4.0的Silverlight版本中,但是Glenn Block确实抛出了源代码.

If it is not right to instantiate the class on import, you can use an ExportFactory<T,TMetadata> which allows you to spin up instances of your types on demand. (ExportFactory is included in the Silverlight version of .NET 4.0, but Glenn Block did throw the source code on codeplex for Desktop/Web use.

我希望能帮上忙.

这篇关于如何从MEF的多个零件中导入特定零件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆