假设我有一个接口IFileLoader和属性FileTypeAttribute
我使用[FileType(" .jpg")]
在JPEGLoader中实现IFileLoader我可以使用MEF加载实现IFileLoader的类(JPEGLoader)并将.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。
答案 0 :(得分: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
接口,您可以向setter
属性添加FileExtension
。实现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"