CompositionContractMismatchException in MetadataViewProvider.cs

Jul 22, 2009 at 1:42 AM
Edited Jul 22, 2009 at 1:44 AM
public interface IMyMetadata {
  string SomeValue { get; }
}
[MetadataAttribute]
public class MyMetadata : ExportAttribute, IMyMetadata {
  public MyMetadata(string arg) : base("BEE1F8C02581424F80FAC7D30E3C8ED8") {
    this.SomeValue = arg;
  }
  public string SomeValue { get; private set; }
}

If a custom metadata class is not decorated with the AttributeUsage(AttributeTargets.Class) attribute, then an CompositionContractMismatchException is thrown at Line 60 in MetadataViewProvider.cs. Is this by behaviour or a bug/known issue?

Exact Exception Message:  Unable to create an Instance of the Metadata view 'MEFTestApp.Contracts.IMyMetadata' because the exporter exported the metadata  for the item 'SomeValue' with the value 'System.String[]' as type 'System.String[]' but the view imports it as type 'System.String'.

Jul 22, 2009 at 5:01 AM

Hi Gomikochar

Can you show the consumer code, that is the part that exports using the MyMetadata attribute, and the importer who imports the contract “BEE1F8C02581424F80FAC7D30E3C8ED8"

Are you saying it works when you do apply the AttributeUsage attribute?

Thanks

Glenn

From: gomikochar [mailto:notifications@codeplex.com]
Sent: Tuesday, July 21, 2009 6:42 PM
To: Glenn Block
Subject: CompositionContractMismatchException in MetadataViewProvider.cs [MEF:63152]

From: gomikochar

public interface IMyMetadata {
  string SomeValue { get; }
}
[MetadataAttribute]
public class MyMetadata : ExportAttribute, IMyMetadata {
  public MyMetadataInfo(string arg) : base("BEE1F8C02581424F80FAC7D30E3C8ED8") {
    this.SomeValue = arg;
  }
  public string SomeValue { get; private set; }
}

If a custom metadata class is not decorated with the AttributeUsage(AttributeTargets.Class) attribute, then an CompositionContractMismatchException is thrown at Line 60 in MetadataViewProvider.cs. Is this by behaviour or a bug/known issue?

Exact Exception Message: Unable to create an Instance of the Metadata view 'MEFTestApp.Contracts.IMyMetadata' because the exporter exported the metadata for the item 'SomeValue' with the value 'System.String[]' as type 'System.String[]' but the view imports it as type 'System.String'.

Read the full discussion online.

To add a post to this discussion, reply to this email (MEF@discussions.codeplex.com)

To start a new discussion for this project, email MEF@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Jul 23, 2009 at 2:14 AM
Edited Jul 23, 2009 at 2:14 AM

Consumer code is as follows:

class Importer {
  [ImportMany("BEE1F8C02581424F80FAC7D30E3C8ED8")]
IEnumerable<Lazy<IFoo, IMyMetadata>> _collection = null; }

And yes, it does work if decorated with the AttributeUsage attribute.

Jul 23, 2009 at 6:24 AM

Thanks gomikochar, we will look into this.

Jul 23, 2009 at 7:10 AM

The reason you are hitting this is due to the way treat metadata attributes that are marked as 'AllowMultiple=true'. When we see such attributes, their metadata values (ie their public properties) are automatically added to metadata as part of a single collections under the same metadata key. For example, let's say you were adding a new editor to Visual Studio, you might have the following:

[AttributeUsage(AttributeTargets.Class, AllowMultiple=true)]
public class ContentTypeAttribute : Attribute
{
    public string Extension
    {
       get;
       set; 
    }
}

Which would be applied to the new editor similar to:

[ContentType(Extension="*.txt")]
[ContentType(Extension="*.log")]
[Export(typeof(IEditor)]
public class MyEditor : IEditor
{
}

On the importer side, the metadata view would look like the following:

public class IEditorMetadata
{
     string[] Extension
     {
         get;
     }
}

In this case, because ContentType is marked as AllowMultiple=true, on the importer side you want to see the associated metadata values pulled from the ContentType attribute combined as a single collection.

In your case, because ExportAttribute is marked as AllowMultiple=true, by default any inherited attribute is treated the same, hence why your values are being exported as 'string[]'. The reason you see a different behavior when you apply the AttributeUsageAttribute is because the default of AttributeUsageAttribute.AllowMultiple is false. This might be a little confusing, but I'm not sure what else we can do.