2011-08-26 17 views
5

Projem için MEF'yi DI olarak kullanmak istiyorum. 1 projem var ve oluşturulacak her sınıf var (bir arabirimi paylaşıyorlar). Şimdi meta veri değerini belirleyerek bunlardan birini oluşturmak istiyorum. MEF GetExportedValue meta verileriyle

public interface IGatewayResponseReader 
{ 
    object Read(string msg); 
} 

[Export(typeof(IGatewayResponseReader))] 
[ExportMetadata(G3Reader.META_KEY, "value1")] 
public class TestReader1 : IGatewayResponseReader 
{ 
    ... 
} 

[Export(typeof(IGatewayResponseReader))] 
[ExportMetadata(G3Reader.META_KEY, "value2")] 
public class TestReader2 : IGatewayResponseReader 
{ 
    ... 
} 

Şimdi MEF yoluyla TestReader1 bir örneğini oluşturmak istiyor ama CompositionContainer yoluyla meta göre filtre uygulamak için nasıl bilmiyorum: İşte tanımlamalar var. Ben, hangi sınıf örneğinin oluşturulacağını seçmek için meta verileri belirtmek istiyorum.

Yardımınız çok takdir edilmektedir.

Teşekkürler.

cevap

6

@Dmitry Ornatsky tarafından takibi cevabın doğru olduğunu, ancak ihracat meta sağlayarak tercih edilen yolu özel ihracat özelliğini kullanarak kesinlikle yazılan meta kullanmaktır: bakmak için

public interface IGatewayResponseReaderMetadata 
{ 
    string Key { get; } 
} 

[MetadataAttribute] 
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property)] 
public class GatewayResponseReaderExportAttribute : ExportAttribute 
{ 
    public GatewayResponseReaderExportAttribute(string key) 
     : base(typeof(IGatewayResponseReader)) 
    { 
     this.Key = key; 
    } 

    public string Key { get; set; } 
} 

[GatewayResponseReaderExport("value1")] 
public class TestReader1 : IGatewayResponseReader 
{ 
} 

kodu Bir ithalat daha sonra güvenli tipte yapılabilir.

class Program 
{ 
    [ImportMany] 
    private List<Lazy<IGatewayResponseReader, IGatewayResponseReaderMetadata>> _readers; 

    static void Main(string[] args) 
    { 
     CompositionContainer container = new CompositionContainer(new AssemblyCatalog(Assembly.GetExecutingAssembly())); 

     Program program = new Program(); 
     container.SatisfyImportsOnce(program); 


     var reader = program._readers.FirstOrDefault(r => r.Metadata.Key == "value1"); 
     if (reader != null) 
      reader.Value.Read(...); 
    } 
} 
+0

Teşekkür Phil, yardımına :) takdir: o ithalat Value özelliği erişmeden önce boş değil olup olmadığını kontrol etmek iyi bir fikir olduğunu unutmayın. Lanet olsun, bu şekilde denedim ve işe yaramadı çünkü MetadataAttribute hakkında bir şey bilmiyordum: (5 saat boyunca bunu anlamaya çalıştım. – Davita

4
class Program 
{ 
    [ImportMany] 
    private List<Lazy<IGatewayResponseReader, IDictionary<string, object>>> _readers; 

    static void Main(string[] args) 
    { 
     CompositionContainer container = new CompositionContainer(new AssemblyCatalog(Assembly.GetExecutingAssembly())); 

     Program program = new Program(); 
     container.SatisfyImportsOnce(program); 
     var result = program._readers.Where(r =>    
      r.Metadata.ContainsKey(G3Reader.META_KEY) && (string)r.Metadata[G3Reader.META_KEY] == "value1") 
      .First().Value; 
    } 
}