.NET Framework Bookmark and Share   
 index > Managed Extensibility Framework > Derived Classes & ExportProperty
 

Derived Classes & ExportProperty

I have the following class structure:

[Export(typeof(IComponent))]
[ExportProperty("ComponentName","base")]
[ExportProperty("Categories","")]
publicclassComponent:IComponent,INotifyImport
{...}
publicclassComponentWithMass:Component
{...}
publicclassConfiguration:INotifyImport
{
[Import(typeof(IComponent))]
publicImportInfoCollection<IComponent,IComponentInfo>Components{get;set;}
publicvoidImportCompleted()
{
Trace.WriteLine(
string.Format("ConfigurationImportCompleted:{0}components",Components.Count));
}
}
publicinterfaceIComponentInfo
{
stringComponentName{get;set;}
stringCategories{get;set;}
}


If I use the following to add instances of these classes to a container:


container.AddComponent
<Component>(new Component("comp1"));
container.AddComponent<Component>(new Component("comp2"));
container.AddComponent<Component>(newComponentWithMass("cm1"));
container.AddComponent<Configuration>(new Configuration());
container.Bind();

Then I see "Configuration Import Completed: 3 components" (from the Configuration.ImportCompleted method).

If however, I decorate ComponentWithMass with

[ExportProperty("ComponentName","ComponentWithMass")]
[ExportProperty("Categories","MassProvider")]

Then the ComponentWithMass instance will not be in the Configuration's Components collection and I see"Configuration Import Completed:2 components".

However, if after the Bind() I do

intcount=container.GetBoundValues<IComponent>().Count();
Trace.WriteLine(string.Format("Containercontains{0}IComponent",count));

Then count will be 3.

So, how do I get the ExportProperty attributes to work on derived classes?
Craig Eddy

Thanks for your feedback kregger!

When a class inherits a component, it also inherits the metadata on the base component. So in your example, "ComponentWithMass" class automatically gets the metadata decorated on the "Component" class. However, when you decorate the same set of metadata ("ComponentName" and "Categories", values are different though)on the derived component (ComponentWithMass) again, they conflicts with the "derived" metadata - container cannot decide which set of metadata you want. So both (the new and derived) metadata are ignored and the ComponentWithMass will end up with no metadata in this case.

When components are importedusingImportInfoCollection<IComponent,IComponentInfo>, the metadata names specified in IComponentInfo will be treated as part of of the contract - that means"ComponentName" and "Categories" are required metadata. On the other hand, because the reason above ComponentWithMass does not have these required metadata, so it will not get bound. Actually, in your example, if you use container.TryBind() instead of container.Bind(), you will receive a CompositionResult and it willreport you an issue ofwarningabout this ignored component due to metadata issues.

When you use container.GetBoundValues<IComponent>() to retrieve bound components, it did not impose any required metadata, so all 3 components get returned.

While this scenariois expected, I think you brought up a verygood point that youexpect metadata can be overwritten in derived components. We will definitely look into this.

Thanks again for your great feedback!

Zhenlan Wang

Thanks for your feedback kregger!

When a class inherits a component, it also inherits the metadata on the base component. So in your example, "ComponentWithMass" class automatically gets the metadata decorated on the "Component" class. However, when you decorate the same set of metadata ("ComponentName" and "Categories", values are different though)on the derived component (ComponentWithMass) again, they conflicts with the "derived" metadata - container cannot decide which set of metadata you want. So both (the new and derived) metadata are ignored and the ComponentWithMass will end up with no metadata in this case.

When components are importedusingImportInfoCollection<IComponent,IComponentInfo>, the metadata names specified in IComponentInfo will be treated as part of of the contract - that means"ComponentName" and "Categories" are required metadata. On the other hand, because the reason above ComponentWithMass does not have these required metadata, so it will not get bound. Actually, in your example, if you use container.TryBind() instead of container.Bind(), you will receive a CompositionResult and it willreport you an issue ofwarningabout this ignored component due to metadata issues.

When you use container.GetBoundValues<IComponent>() to retrieve bound components, it did not impose any required metadata, so all 3 components get returned.

While this scenariois expected, I think you brought up a verygood point that youexpect metadata can be overwritten in derived components. We will definitely look into this.

Thanks again for your great feedback!

Zhenlan Wang
We have built an extensive system of run-time loading sets of components all deriving from a common base, but decorated with various attributes and augmented @ runtime by data from XML files. The more I experiment with MEF the more convinced I am we should migrate our code to use the framework.

However, we'll need to be able to (well maybe need is strong, we could still do queries based on our existing attributes, I think) to be able to override ExportProperty values in the derived classes.

Thanks for the quick response!
  • Edited byCraig Eddy Friday, June 13, 2008 12:29 PMgrammer error
  •  
Craig Eddy

You can use google to search for other answers

Custom Search

More Threads

• Order of ImportCompleted
• No "hard dependancy" but a new dependancy is introduced.
• how to add or integrate download accelerator to IE
• How to identify, Is current user a Administrator..?
• Do you support the Default export option
• no microphone
• Comparison to the AddIn libraries?
• Why multi ExportAttribute is not supportted by property?
• wrong csv information showed up in csv file
• Several contributors to unity configuration in app.config ?