MEF 1 + nHibernate + Fluent NHibernate - Cannot cast (ContractName=“NHibernate.ISession”)' to type 'NHibernate.ISession'

Sep 18, 2013 at 12:18 AM
I've been wrestling with this issue for about two weeks now and have cut it back to one very specific test. I've asked this question on StackOverflow but haven't had any helpfull replies as yet.

Please note I cannot use .Net 4.5 due to customers operating systems.

Bascially I've got a session factory class which imports the fluent configuration and exports new NHibernate ISessions through a function with the attribute [Export(typeof(ISession))].

The code for this class is as follows:
[Export(typeof(SessionFactoryMock))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class SessionFactoryMock
{
    private readonly ISessionFactory sessionFactory;        

    public SessionFactoryMock()
    {
        sessionFactory =
                Fluently.Configure()
                .Database(
                    MsSqlConfiguration.MsSql2008.ConnectionString(c => c
                        .Server(@".\SQLExpress")
                        .Database("Test")
                        .TrustedConnection()))
                .Mappings(configuration => configuration.FluentMappings.Add<TestEntityMap>())
                .ExposeConfiguration(c => new SchemaExport(c).Execute(true, true, false))                    
                .BuildSessionFactory();            
    }

    [Export(typeof(ISession))]
    public ISession GetSession()
    {
        return sessionFactory.OpenSession();
    }
}
And I'm using the following test to see if I can get a session from the session factory:
[TestMethod]
public void CanGetISession()
{
    Assembly executing = Assembly.GetExecutingAssembly();
    var cat = new AggregateCatalog(new[]
        {
            new AssemblyCatalog(executing)
        });

    var container = new CompositionContainer(cat);

    var batch = new CompositionBatch();
    batch.AddExportedValue(container);

    container.Compose(batch);

    var compositionInfo = new CompositionInfo(cat, container);
    using (var stringWriter = new StringWriter())
    {
        CompositionInfoTextFormatter.Write(compositionInfo, stringWriter);
        string compositionDetail = stringWriter.ToString();
        bool errorDetected = compositionDetail.Contains("[Primary Rejection]");

        if (errorDetected)
        {
            Assert.Fail(compositionDetail);
        }
    }

    var export = container.GetExport<ISession>();
    var exportedValue = export.Value;
    Assert.IsNotNull(exportedValue);
}
This test will continually fail with the message:

System.ComponentModel.Composition.CompositionContractMismatchException: Cannot cast the underlying exported value of type 'MefnHibernateFail.SessionFactoryMock.GetSession (ContractName="NHibernate.ISession")' to type 'NHibernate.ISession'.

Which is extremely unhelpful.

I'm building all the Fluent nHibernate and NHibernate libraries from code and I have an example solution.

I'm really hoping someone can shed some light on this because I'm pretty much at a dead end now. The only way forward I can see is to pull out MEF and use another IOC framework.

Full source code can be found here: Example Solution