Sti*_*lon 7 .net c# reflection mef
假设我有一个接口IFileLoader和属性FileTypeAttribute
我用[FileType(".jpg")]在JPEGLoader中实现IFileLoader
我可以使用MEF加载实现IFileLoader的类(JPEGLoader)并将.jpg作为文件扩展名匹配,这样我就可以实现以下方法:
public void IFileLoader GetLoader(string filename);
Run Code Online (Sandbox Code Playgroud)
可以用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);
Run Code Online (Sandbox Code Playgroud)
或者上面至少变成了ILookup,或者是其他我没想过的东西?
我希望能够在项目的不同程序集中甚至在插件程序集中实现IFileLoader.
可以通过使用MEF并将其附加Metadata到导出的部件来获取您需要的文件加载器。
创建元数据接口和属性。
public interface IFileTypeMetadata
{
string FileExtension { get; }
}
Run Code Online (Sandbox Code Playgroud)
该界面可以包含您需要的任意数量的属性。对于这个特定问题,它只包含一个属性FileExtension。重要的是该属性只有getter. MEF旨在不允许在运行时更改元数据。然后创建保存元数据的属性:
public class FileTypeAttribute : Attribute, IFileTypeMetadata
{
public string FileExtension { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
该类FileTypeAttribute实现了IFileTypeMetadata接口,您可以将 a 添加setter到FileExtension属性中。它是实现FileLoader类所必需的,并且MEF不会抱怨,因为我们将通过IFileTypeMetadata接口访问元数据,其中包含的属性仅具有getters
创建文件加载器类实现的接口和文件加载器类。
public interface IFileLoader
{
string LoadFile();
}
Run Code Online (Sandbox Code Playgroud)
为了简单起见,该接口仅包含一种方法。这是两个不同的虚拟文件加载器类的示例:
[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";
}
}
Run Code Online (Sandbox Code Playgroud)
这两个类都实现了IFileLoader接口并作为部件导出IFileLoader,但它们通过FileType属性具有不同的元数据。
创建组合容器
var catalog = new DirectoryCatalog("path to directory where dll's are located");
var compositionContainer = new CompositionContainer(catalog);
compositionContainer.ComposeParts();
Run Code Online (Sandbox Code Playgroud)
访问导出的零件
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"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2057 次 |
| 最近记录: |