2

我对 MEF 完全陌生,想在我目前正在开发的项目中使用它。

想法:我想写一个FileLoader<T>T作为我试图加载的类型的参数,并为我提供支持将哪些文件扩展名加载到这种类型中的数据。类型加载器在分散在解决方案中的类中提供,Func<string, T>并且应该由 MEF 收集到IEnumerable. 然后从元数据中收集支持的文件类型。

现在我就是这样做的:

[Export(typeof(IFileLoader<>))]
class FileLoader<TData> : IFileLoader<TData>
{
    static FileLoader()
    {
        SimpleIoc.Default.Register(() => { return new FileLoader<Model.CompositeSignal<Model.SignalBase>>(); });
    }

    [ImportMany(typeof(Func<string, TData>))] // Problem here!!!
    private IEnumerable<Func<string, TData>> Loaders { get; set; }

    public FileLoader()
    {
        //TODO: Compose here
    }

    public IEnumerable<FileExtensionFilter> GetSupportedFiletypes()
    {
        throw new NotImplementedException();
    }

    public TData LoadFromFile(string filename)
    {
        throw new NotImplementedException();
    }
}

//////////////// Somewhere else in a class //////////////////////////////////////

    [Export(typeof(Func<string, CompositeSignal<SignalBase>>))]
    [SupportedFileType(FileTypeDescription="Signal interpolation file", FileTypeMask="*.interpol.xml")]
    public CompositeSignal<InterpolatedSignal> InterpolationFileLoader(string filename)
    {
        throw new NotImplementedException(); //TODO
    }

////////////////////////////////////////////////////////////////////////////////

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Method, AllowMultiple=true)]
public class SupportedFileTypeAttribute : Attribute
{
    public string FileTypeDescription { get; set; }
    public string FileTypeMask { get; set; }

    public SupportedFileTypeAttribute() 
        : base() 
    { } 
}

问题是我不能在 ImportMany 属性的 typeof 中有一个通用参数。现在,我当然可以尝试导入所有类型加载器并循环遍历它们,但我无法想象这是一个优雅的解决方案。

最好的方法是什么?

提前致谢。

4

1 回答 1

2

我不认为循环访问该Loaders属性是一件坏事。您只需执行一次(或每次发生重组,如果您设置AllowRecomposition = True)。

我会让元数据指定它加载的数据类型,并根据它提取想要的加载器。这基本上就是元数据的用途。如果您使用Lazy<T, TMetadata>,则甚至不会创建您不使用的类型。

于 2012-09-11T19:34:59.717 回答