MEF2: Error with GetExport: "Specified method is not supported"

Dec 6, 2011 at 6:58 AM

Anyone an idea?

It is a QUITE simple base class that I try to compose here.

The following code works fine:

 

Application application = new Application();
container.SatisfyImportsOnce(application);

 

(container is the CompositionContainer).

The following code blows:

 

var export = container.GetExport<Application>();

 

The error is: NotSupportedException, the stack trace:

Server stack trace: 
   at System.Reflection.Emit.TypeBuilderInstantiation.IsSubclassOf(Type c)
   at System.ComponentModel.Composition.ContractNameServices.GetTypeIdentity(Type type, Boolean formatGenericName)
   at System.ComponentModel.Composition.ContractNameServices.GetTypeIdentity(Type type)
   at System.ComponentModel.Composition.AttributedModelServices.GetTypeIdentity(Type type)
   at System.ComponentModel.Composition.Hosting.CompositionServices.GetTypeIdentityFromExport(MemberInfo member, Type typeIdentityType)
   at System.ComponentModel.Composition.Hosting.CompositionServices.GetContractInfoFromExport(MemberInfo member, ExportAttribute export, Type& typeIdentityType, String& contractName)
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.CreateExportDefinition(MemberInfo member, ExportAttribute exportAttribute)
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.GetExportDefinitions()
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.DiscoverExportsAndImports()
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.GetExports()
   at System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePartDefinition.get_ExportDefinitions()
   at System.ComponentModel.Composition.Hosting.TypeCatalog.CreateIndex()
   at System.Lazy`1.CreateValue()

Exception rethrown at [0]: 
   at System.Reflection.Emit.TypeBuilderInstantiation.IsSubclassOf(Type c)
   at System.ComponentModel.Composition.ContractNameServices.GetTypeIdentity(Type type, Boolean formatGenericName)
   at System.ComponentModel.Composition.ContractNameServices.GetTypeIdentity(Type type)
   at System.ComponentModel.Composition.AttributedModelServices.GetTypeIdentity(Type type)
   at System.ComponentModel.Composition.Hosting.CompositionServices.GetTypeIdentityFromExport(MemberInfo member, Type typeIdentityType)
   at System.ComponentModel.Composition.Hosting.CompositionServices.GetContractInfoFromExport(MemberInfo member, ExportAttribute export, Type& typeIdentityType, String& contractName)
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.CreateExportDefinition(MemberInfo member, ExportAttribute exportAttribute)
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.GetExportDefinitions()
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.DiscoverExportsAndImports()
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.GetExports()
   at System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePartDefinition.get_ExportDefinitions()
   at System.ComponentModel.Composition.Hosting.TypeCatalog.CreateIndex()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at System.Lazy`1.get_Value()
   at System.ComponentModel.Composition.Hosting.TypeCatalog.GetCandidateParts(String contractName)
   at System.ComponentModel.Composition.Hosting.TypeCatalog.GetCandidateParts(ImportDefinition definition)
   at System.ComponentModel.Composition.Primitives.ComposablePartCatalog.GetExports(ImportDefinition definition)
   at System.ComponentModel.Composition.Hosting.AssemblyCatalog.GetExports(ImportDefinition definition)
   at System.ComponentModel.Composition.Hosting.AggregateCatalog.GetExports(ImportDefinition definition)
   at System.ComponentModel.Composition.Hosting.CatalogExportProvider.InternalGetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.CatalogExportProvider.InnerCatalogExportProvider.GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExports(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.CatalogExportProvider.GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExports(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.AggregateExportProvider.GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExports(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.AggregateExportProvider.GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExports(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.CompositionContainer.GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.ExportProvider.GetExports(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.GetExportsCore(Type type, Type metadataViewType, String contractName, ImportCardinality cardinality)
   at System.ComponentModel.Composition.Hosting.ExportProvider.GetExportCore[T](String contractName)
   at System.ComponentModel.Composition.Hosting.ExportProvider.GetExport[T](String contractName)
   at System.ComponentModel.Composition.Hosting.ExportProvider.GetExport[T]()
   at CodeCore.ApplicationModel.Application.CreateApplication(CompositionContainer additionalRoot) in C:\Work\CodeCore\Source\CodeCore\ApplicationModel\Application.cs:line 136
   at CodeCore.Tests.ApplicationModel.ApplicationTests.CreateApplication() in C:\Work\CodeCore\Source\CodeCore.Tests\ApplicationModel\ApplicationTests.cs:line 19

The code for the Application class is currently trivial - a handfull of properties and methods. Nothing gets imported (it is all commented out). I am totally at a loss here what is going wrong (mostly because it is very deep internally and no context is available / provided.

Just as note: this is from the latest preview available for download here.

Dec 6, 2011 at 7:42 AM

As additional note:

I checekd some public source code and the blowing method seems to be not implemented?

http://labs.developerfusion.co.uk/SourceViewer/browse.aspx?assembly=SSCLI&namespace=System.Reflection.Emit&type=TypeBuilderInstantiation

and

http://www.koders.com/csharp/fid90B814DACEBAAB025E0C8F4747C03F9B1035E65B.aspx

both note IsSubclassOf as just throwing a NotSupportedException.

No access to the current code, but I am using the .Codeplex assemblies. If that is still true, then, basically, this is a pretty bad choice for a subclass identifier ;) Please advice ;)

Coordinator
Dec 6, 2011 at 6:08 PM

If its not too much trouble could you send us the code for the application class, so we could repro this. We are looking at this and a repro might be the quickest way to get to the bottom of this.

Thanks

-alok

Coordinator
Dec 6, 2011 at 6:17 PM

just  a clarification, a simple sketch of the what your Applicaiton class looks like would be fine, : ) , we don`t need the actual source code.

thanks

-alok

 

Dec 6, 2011 at 7:11 PM
Does it have an Export attribute on it?

Sent from my Windows Phone

From: NetTecture
Sent: 12/5/2011 10:58 PM
To: Glenn Block
Subject: MEF2: Error with GetExport: "Specified method is not supported" [MEF:281932]

From: NetTecture

Anyone an idea?

It is a QUITE simple base class that I try to compose here.

The following code works fine:

Application application = new Application();
container.SatisfyImportsOnce(application);

(container is the CompositionContainer).

The following code blows:

var export = container.GetExport<Application>();

The error is: NotSupportedException, the stack trace:

Server stack trace: 
   at System.Reflection.Emit.TypeBuilderInstantiation.IsSubclassOf(Type c)
   at System.ComponentModel.Composition.ContractNameServices.GetTypeIdentity(Type type, Boolean formatGenericName)
   at System.ComponentModel.Composition.ContractNameServices.GetTypeIdentity(Type type)
   at System.ComponentModel.Composition.AttributedModelServices.GetTypeIdentity(Type type)
   at System.ComponentModel.Composition.Hosting.CompositionServices.GetTypeIdentityFromExport(MemberInfo member, Type typeIdentityType)
   at System.ComponentModel.Composition.Hosting.CompositionServices.GetContractInfoFromExport(MemberInfo member, ExportAttribute export, Type& typeIdentityType, String& contractName)
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.CreateExportDefinition(MemberInfo member, ExportAttribute exportAttribute)
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.GetExportDefinitions()
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.DiscoverExportsAndImports()
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.GetExports()
   at System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePartDefinition.get_ExportDefinitions()
   at System.ComponentModel.Composition.Hosting.TypeCatalog.CreateIndex()
   at System.Lazy`1.CreateValue()

Exception rethrown at [0]: 
   at System.Reflection.Emit.TypeBuilderInstantiation.IsSubclassOf(Type c)
   at System.ComponentModel.Composition.ContractNameServices.GetTypeIdentity(Type type, Boolean formatGenericName)
   at System.ComponentModel.Composition.ContractNameServices.GetTypeIdentity(Type type)
   at System.ComponentModel.Composition.AttributedModelServices.GetTypeIdentity(Type type)
   at System.ComponentModel.Composition.Hosting.CompositionServices.GetTypeIdentityFromExport(MemberInfo member, Type typeIdentityType)
   at System.ComponentModel.Composition.Hosting.CompositionServices.GetContractInfoFromExport(MemberInfo member, ExportAttribute export, Type& typeIdentityType, String& contractName)
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.CreateExportDefinition(MemberInfo member, ExportAttribute exportAttribute)
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.GetExportDefinitions()
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.DiscoverExportsAndImports()
   at System.ComponentModel.Composition.AttributedModel.AttributedPartCreationInfo.GetExports()
   at System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePartDefinition.get_ExportDefinitions()
   at System.ComponentModel.Composition.Hosting.TypeCatalog.CreateIndex()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at System.Lazy`1.get_Value()
   at System.ComponentModel.Composition.Hosting.TypeCatalog.GetCandidateParts(String contractName)
   at System.ComponentModel.Composition.Hosting.TypeCatalog.GetCandidateParts(ImportDefinition definition)
   at System.ComponentModel.Composition.Primitives.ComposablePartCatalog.GetExports(ImportDefinition definition)
   at System.ComponentModel.Composition.Hosting.AssemblyCatalog.GetExports(ImportDefinition definition)
   at System.ComponentModel.Composition.Hosting.AggregateCatalog.GetExports(ImportDefinition definition)
   at System.ComponentModel.Composition.Hosting.CatalogExportProvider.InternalGetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.CatalogExportProvider.InnerCatalogExportProvider.GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExports(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.CatalogExportProvider.GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExports(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.AggregateExportProvider.GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExports(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.AggregateExportProvider.GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExports(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.CompositionContainer.GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1& exports)
   at System.ComponentModel.Composition.Hosting.ExportProvider.GetExports(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.GetExportsCore(Type type, Type metadataViewType, String contractName, ImportCardinality cardinality)
   at System.ComponentModel.Composition.Hosting.ExportProvider.GetExportCore[T](String contractName)
   at System.ComponentModel.Composition.Hosting.ExportProvider.GetExport[T](String contractName)
   at System.ComponentModel.Composition.Hosting.ExportProvider.GetExport[T]()
   at CodeCore.ApplicationModel.Application.CreateApplication(CompositionContainer additionalRoot) in C:\Work\CodeCore\Source\CodeCore\ApplicationModel\Application.cs:line 136
   at CodeCore.Tests.ApplicationModel.ApplicationTests.CreateApplication() in C:\Work\CodeCore\Source\CodeCore.Tests\ApplicationModel\ApplicationTests.cs:line 19

The code for the Application class is currently trivial - a handfull of properties and methods. Nothing gets imported (it is all commented out). I am totally at a loss here what is going wrong (mostly because it is very deep internally and no context is available / provided.

Just as note: this is from the latest preview available for download here.

Dec 6, 2011 at 7:41 PM

Yes, it has. It seems to be related to RegistrationBuilder. The setup is more complex - application references some other types.

I managed to nail something else down, though:

It does not related to the Application or other objects directly, but to RegistrationBuilder.

The error happens when I am adding an AssemblyCatalog with a RegistrationBuilder - REGARDLESS (!) whether there is anything set up there. Even a simple new RegistrationBuilder () just is enough to create the error. if I keep away from RegistrationBuilder, things work fine. Note - as I said - that this also happens with NO export or anything defined for the RegistrationBuilder.

And yes, there are Export attributes. I am actually still using those (want to move to RegistrationBuilder later on).

 

 

Dec 6, 2011 at 10:20 PM

The top of the stack (TypeBuilderInstantiation) is generally associated with Reflection.Emit. Are you using any custom interception/proxying mechanisms with your container?

Thanks,
Nick

Dec 6, 2011 at 10:22 PM

No, nothing. This is currently an "as easy as possible" test case. There are a couple of empty classes around but no logic anywhere. The calling application is... mstest (unit tests).

Dec 13, 2011 at 7:54 PM

Thanks - we're still looking into this one. If it is possible, it would be a great help if you could provide a standalone test case that reproduces the issue.

For example, using the Preview 4 drop, the test case below passes. I suspect that the error is related to discovery of another type in the catalog other than the Application class you have described.

Thanks again!

using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Registration;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTestProject1
{
    [Export]
    public class Application { }

    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            var cc = new CompositionContainer(
                new TypeCatalog(
                    new[] { typeof(Application) },
                    new RegistrationBuilder()));

            var a = cc.GetExport<Application>();

            Assert.IsInstanceOfType(a.Value, typeof(Application));
        }
    }
}

Feb 5, 2012 at 4:38 AM
Edited Feb 5, 2012 at 4:40 AM

Nicholas,

Here is an update on this, I hope it will help you to resolve the issue.

This happens when you try to create an open generic export with a contract which is NOT an interface and also use a RegistrationBuilder.

Those fancypants custom reflection contexts (which RegBuilder inherits from) simply go and wrap ALL types regardless of whether there are any changes or not. And they do the wrapping with a little help from System.Reflection.Emit, which produces a TypeBuilderInstantiation, whose method .IsSubclassOf is simply not implemented and always throws a NotSupportedException. Look at the source code (or with ILSpy as I do) and you'll see.

So when you try to do this, the following line in ContractNameService.cs fails (line 53 in my version of the source code):

      if ( !type.IsAbstract && type.IsSubclassOf( typeof( Delegate ) ) )

This doesn't happen when the export contract is an interface, because the IsAbstract part of the condition returns true and the condition doesn't get evaluated further. And it doesn't happen when there is no RegBuilder, because in that case IsSubclassOf does not throw an exception.

Now, in order to fix this, simply get rid of the .IsSubclassOf call and replace it with an .IsAssignableFrom.

In conclusion, here is a test case for ya:

 

    [Export(typeof(SomeClass<,>))] class SomeClass<T,U> { }

    [TestMethod]
    public void ContractNameServices_IsSubclassOfFails()
    {
        var reg = new Registration.RegistrationBuilder();
        var container = new CompositionContainer( new TypeCatalog( new[] { typeof( SomeClass<,> ) }, reg ) );
        var v = container.GetExportedValue<SomeClass<int,string>>();
        Assert.IsInstanceOfType( v, typeof( SomeClass<int,string> ) );
    }

Feb 6, 2012 at 6:29 PM

Excellent - thank you kindly for the repro.

Nick

Feb 7, 2012 at 9:12 AM

Wonderfull. I am ashamed - I had given up on the issue and wanted to wait for the next preview release to hope for an accidental fix. Your repro makes it clear where the issue lies and provides a workaround/fix already integrated. Let's hope those people maintaining that excellent framework manage to fix it for the beta coming ;)