Search code examples
c#nhibernatefluent-nhibernatemef

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


I've been wrestling with this issue for about two weeks now and have cut it back to one very specific test.

Bascially I've got a session factory which configures the NHibernate session factory and has a function which [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:

    [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.

Full source code can be found here: Source


Solution

  • For anyone else having the same issue. The problem was that the export on the function should be [Export(typeof(Func<ISession>)] not [Export(typeof(ISession))]. MEF passes the function pointer not the pointer to the returned object (which is why my function was never called).