2011-11-02 55 views
3

我有一個應用程序,它可以導出多個相同類的對象,以及只導入特定類的對象。例如C#MEF:導出一個類型的多個對象,並導入特定的對象

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

有人可以解釋我怎麼能實現這種行爲?

回答

4

你需要一個合同(接口)和元數據的合同(接口):

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和懶惰導入:

[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; 
     } 
    } 
+0

這種方法相對於Adam提出的優點是什麼?這種方法是不是需要更多的開銷,並且不會在一點上導入所有對象,只訪問你想使用的方法(即那些定義爲個案的方法)?如果我最終得到超過100個對象,這會阻礙只有1或2個插件才能使用的插件性能。 –

+0

如果您需要幾次導入,您可以使用Adam方法。另一方面,當您有很多導入時,Lazy類很有用。 - >「實際上懶惰是當你的插件很重,需要大量內存時使用的」http://dailydotnettips.com/2011/09/02/getting-lazy-with-mef/ – Galled

+0

此外,你需要一個合同來確保您的解決方案將隨着時間的推移而保持不變,因爲通過合同您可以在不接觸主項目的情況下改變您的出口類。如果你在沒有合同的情況下放置這些名字將非常依賴於這些零件,你將失去一些MEF的好處。 – Galled

10

可以命名出口:

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

當你想要一個特定的一個,

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

,您仍然可以導入許多類型部分,如果你不指定名稱。

+0

非常好,謝謝! –

+1

如果我的回答解決了您的問題,請務必將其標記爲答案。 –

+0

@AdamBarney,找到你的答案,在SL中做同樣的事,但它不起作用,你是否看到任何明顯的錯誤? http://stackoverflow.com/questions/39758390/exporting-by-type-and-contract-importmany-does-not-work-as-expected – katit