【问题标题】:C# MEF: Exporting multiple objects of one type, and Importing specific onesC# MEF:导出一种类型的多个对象,并导入特定对象
【发布时间】:2011-12-20 08:34:38
【问题描述】:

我有一个应用程序可以导出同一个类的多个对象,以及只导入特定对象的插件。例如

public class Part
{
  string name;
  public Part(string nm)
  {
    name = nm;
  }
}

public class Car //Exports ALL Parts of the Car
{
  [Export(typeof(Part))]
  public Part steeringWheel = new Part("SteeringWheel");

  [Export(typeof(Part))]
  public Part engine = new Part("Engine");

  [Export(typeof(Part))]
  public Part brakes = new Part("Brakes");
}

public class SystemMonitorPlugin //Imports only SOME Parts from the Car
{
  [Import(typeof(Part))]
 public Part engine;

  [Import(typeof(Part))]
  public Part brakes;
}

有人可以解释我如何实现这种行为吗?

【问题讨论】:

    标签: c# wpf import export mef


    【解决方案1】:

    你需要一个合约(接口)和一个元数据合约(接口):

    public interface ICarPart{
        int SomeMethodFromInterface();
    }
    
    public interface ICarPartMetadata{
        string /*attention to this!!!*/ NameCarPart { get; } /* Only for read. */
    }
    

    然后你导出你的零件:

    [Export(typeof (ICarPart))]
    [ExportMetadata("NameCarPart","SteeringWheel")] /* is string!! */
    
    public class SteeringWheel : ICarPart {
    
        public int SomeMethodFromInterface(){
            ... //your stuff
        }
    }
    [Export(typeof (ICarPart))]
    [ExportMetadata("NameCarPart","Engine")] /* is string!! */
    
    public class Engine : ICarPart {
    
        public int SomeMethodFromInterface(){
            //Each method have diferent behavior in each part.
            ... //your stuff
        }
    }
    [Export(typeof (ICarPart))]
    [ExportMetadata("NameCarPart","Brakes")] /* is string!! */
    
    public class Brakes : ICarPart {
    
        public int SomeMethodFromInterface(){
            //Each method have diferent behavior in each part.
            ... //your stuff
        }
    }
    

    然后你可以使用 ImportMany 和 Lazy 导入:

        [ImportMany()]
        IEnumerable<Lazy<ICarPart, ICarPartMetadata>> carParts = null;
        public void Importing(){
        ...
        ...
    
        foreach (Lazy<ICarPart,ICarPartMetadata> item in carParts){
            switch (item.Metadata.ICarPartMetadata.ToString()){
                case "SteeringWheel":
                    item.Value.SomeMethodFromInterface();
                break;
                case "Engine":
                    item.Value.SomeMethodFromInterface();
                break;
                case "Brakes":
                    item.Value.SomeMethodFromInterface();
                break;
                default:
                ...
                break;
            }
        }
    

    【讨论】:

    • 这种方法比 Adam 提出的方法有什么优势?这种方法不会需要更多的开销,并且这不会在某一时刻导入所有对象,只访问您希望使用的方法(即定义为案例的方法)吗?如果我最终得到超过 100 个对象,这会影响仅访问其中 1 或 2 个的插件的性能,不是吗?
    • 如果您需要一些导入,您可以使用 Adam 方法。另一方面,当您有大量导入时,Lazy 类很有用。 -> “当你的插件很重并且需要大量内存时,实际上会使用 Lazy”dailydotnettips.com/2011/09/02/getting-lazy-with-mef
    • 此外,您需要一个合同来确保您的解决方案将随着时间的推移得到维护,因为有了合同,您可以在不接触主项目的情况下更改您的导出类。如果你把名字没有合同会非常依赖的部分,你会失去一些MEF的好处。
    【解决方案2】:

    您可以命名导出:

    [Export("SteeringWheel", typeof(Part))]
    

    当你想要一个特定的,

    [Import("Engine", typeof(Part))]
    

    如果不指定名称,仍然可以导入许多类型的 Part。

    【讨论】:

    • 如果我的回复解决了您的问题,请务必将其标记为答案。
    • @AdamBarney,找到了你的答案,在 SL 中做同样的事情但它不起作用,你有什么明显的错误吗? stackoverflow.com/questions/39758390/…
    猜你喜欢
    • 2011-03-02
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    • 2016-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多