I'm totally new to MEF and wanted to use it in a project I'm currently developing.
Idea: I want to write a FileLoader<T>
which takes T
as argument for type I'm trying to load and provides me data on which file extensions are supported to load into this type. The type loaders are provided in classes scattered in the solution as Func<string, T>
and should be collected by MEF into IEnumerable
. The supported file types are then collected from metadata.
Now that's how I was trying to do it:
[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()
{ }
}
The problem is I can't have a generic parameter in a typeof in the ImportMany attribute. Now, I could of course just try to import all type loaders and loop through them, but I can't imagine that's an elegant solution.
What could be the best way to do it?
Thanks in advance.
I don't think looping through the Loaders
property is such a bad thing. You only need to do it once (or each time a recomposition occurs, if you set AllowRecomposition = True
).
I'd have the metadata specify the type of data it loads, and extract the wanted loaders according to it. That's basically what metadata is for. If you'll use Lazy<T, TMetadata>
, the types you don't use won't even be created.