Reputation: 1809
Good day, can you please assist me in this complex task. I developing module app with MEF. Each module have metadata like this:
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public abstract class ModuleMetadata : ExportAttribute, IArmModuleMetadata
{
private ModuleDescriptor _descriptor;
public ModuleMetadata(string name, string code, string category, string iconUri)
: base()
{
_descriptor = new ModuleDescriptor(name, code, category, iconUri);
}
}
I use it like this:
[Export(typeof(IArmTaskModule))]
[TaskModuleMetadata("test1", "code",
@"pack://application:,,,/WpfVisualModule;component/Icons/chart_line_error.png",
"road_weather_stations",
TargetItem = TargetItems.ControlComplex)]
class AdvancedChartContract : Burstroy.Arm.Contracts.IArmTaskModule
For each module there is a set of properties generated by Dictionary<string, Settings.ParamDescriptor> CreateSettingsBlock()
method in IArmModule
, where Key contains code of property and Value contains fancy name and default value.
In my main app i use Lazy<T, TMetadata>
for importing modules like this
[ImportMany(typeof(IArmTaskModule), AllowRecomposition = true)]
private IEnumerable<Lazy<IArmTaskModule, IArmTaskModuleMetadata>> _taskModules;
The problem in this approach that Lazy<T, TMetadata>
will create instance of IArmTaskModule
for recieving settings block from method. I want to prevent itby adding properties info to metadata. I tried to extend attrribute constructor with new List () but it's failed (attribute restriction),
i also tried to make new attribute
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class ExportedParam : ExportAttribute, IArmModuleProperty
{
public ExportedParam(string code, string fancyName)
: base()
{
this.Code = code;
this.FancyName = fancyName;
//this.Value = value;
}
public string Code { get; private set; }
public string FancyName { get; private set; }
public object Value { get; private set; }
}
but it's failed either.
[ExportedParam("a", "b")]
[ExportedParam("b", "c")]
[ExportMetadata("fffffuuu", 2)]
class MeteoSummary : IArmVisualModule,
Does anyone have any suggestions?
Upvotes: 2
Views: 4167
Reputation: 4172
The ModuleMetadata
class does not follow the custom export attribute guidelines.
It should be like:
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public abstract class ModuleMetadataExportAttribute : ExportAttribute
{
public ModuleDescriptor Descriptor { get; private set; }
public ModuleMetadata(string name, string code, string category, string iconUri)
: base(typeof(IArmTaskModule))
{
Descriptor= new ModuleDescriptor(name, code, category, iconUri);
}
}
And your metadata interface like this:
public interface IArmModuleMetadata
{
ModuleDescriptor Descriptor { get; }
}
Note that:
I also changed the name of the custom attribute class to conform with the guidelines for creating custom attributes (I cannot find a source for this right now but you could check the Framework Design Guidelines 2nd edition by Cwalina, Abrams). This is not necessary though.
Then you export like this:
[ModuleMetadataExport(...))] //Add your params here.
[TaskModuleMetadata("test1", "code",
@"pack://application:,,,/WpfVisualModule;component/Icons/chart_line_error.png",
"road_weather_stations",
TargetItem = TargetItems.ControlComplex)]
class AdvancedChartContract : Burstroy.Arm.Contracts.IArmTaskModule
I left TaskModuleMetadata
because I don't know what it is. I assume it doesn't have to do with MEF.
Finally do keep the import part unchanged. Then when you iterate over the _taskModules
sequence you will access the Value
property only after you have checked the Metadata
property and made sure that the current module is the one you want. Then you access the Value
property and the Module will be created.
Upvotes: 1