2014-05-13 101 views
6

可以說我有一個接口IFileLoader和屬性FileTypeAttributeMEF負載類型屬性

而且我在JPEGLoader與實施IFileLoader [文件(「JPG」)

我可以使用MEF加載類(JPEGLoader)實現IFileLoader和匹配的.jpg的文件擴展名,所以我可以實現以下方法:

public void IFileLoader GetLoader(string filename); 

可以這樣用MEF做,或者我應該堅持這一點:

var allTypes = assemblies.SelectMany(a => a.GetTypes()); 
var classes = allTypes.Where(t => t.IsClass && ! t.IsAbstract); 
var fileLoaders = classes.where(t => typeof(IFileLoader).IsAssignableFrom(t)); 
var forType = fileLoaders.Where(t => t.GetAtributeValue<FileTypeAttribute,string>(t => t.FileType, string.Empty) == fileType); 
var loaderInstances = fileLoaders.Select(t => Activator.CreateInstance(t) as IFileLoader); 

或者上面至少變成了ILookup,或者其他的東西我沒有考慮過?

我希望能夠在項目的不同程序集甚至插件程序集中實現IFileLoader。

回答

2

通過將MEF和attachnig Metadata用於導出的零件,可以獲得所需的文件加載器。

創建元數據接口和屬性。

public interface IFileTypeMetadata 
{ 
    string FileExtension { get; } 
} 

接口可以包含你需要儘可能多的性能。對於這個特定的問題,它只包含一個屬性FileExtension。該物業只有getter是重要的。 MEF被設計爲不允許在運行時改變元數據。然後創建包含元數據屬性:

public class FileTypeAttribute : Attribute, IFileTypeMetadata  
{   
    public string FileExtension { get; set; } 
} 

FileTypeAttribute類實現IFileTypeMetadata接口,您可以添加一個setterFileExtension財產。這是需要實現的FileLoader類和MEF不會抱怨,因爲我們將通過IFileTypeMetadata接口包含有唯一getters

創建文件加載器類實現的接口和文件加載類的屬性訪問元數據。

public interface IFileLoader 
{ 
    string LoadFile(); 
} 

該接口僅包含一個爲簡單起見方法。這裏是例如兩個不同的虛擬文件加載類:

[Export(typeof(IFileLoader))] 
[FileType(FileExtension = ".jpg")] 
public class JpgFileLoader : IFileLoader 
{ 
    public string LoadFile() 
    { 
     return "JPG"; 
    } 
} 

[Export(typeof(IFileLoader))] 
[FileType(FileExtension = ".png")] 
public class PngFileLoader : IFileLoader 
{ 
    public string LoadFile() 
    { 
     return "PNG"; 
    } 
} 

兩個類都實現了IFileLoader接口,並導出爲IFileLoader部分,但它們有不同的元數據,通過FileType屬性。

創建組合物容器

var catalog = new DirectoryCatalog("path to directory where dll's are located"); 
var compositionContainer = new CompositionContainer(catalog); 
compositionContainer.ComposeParts(); 

訪問導出部分

var fileLoaders = compositionContainer.GetExports<IFileLoader, IFileTypeMetadata>(); 

var jpgFileLoader = fileLoaders.FirstOrDefault(x => x.Metadata.FileExtension == ".jpg"); 

if (jpgFileLoader != null) 
    Console.WriteLine(jpgFileLoader.Value.LoadFile()); //should print "JPG" 

var pngFileLoader = fileLoaders.FirstOrDefault(x => x.Metadata.FileExtension == ".png"); 

if (pngFileLoader != null) 
    Console.WriteLine(pngFileLoader.Value.LoadFile()); //should print "PNG"