Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to map an interface in nhibernate?

I'm using two class NiceCustomer & RoughCustomer which implment the interface ICustomer.

The ICustomer has four properties. They are:

  1. Property Id() As Integer
  2. Property Name() As String
  3. Property IsNiceCustomer() As Boolean
  4. ReadOnly Property AddressFullText() As String

I don't know how to map the interface ICustomer, to the database.

I get an error like this in the inner exception.

An association refers to an unmapped class: ICustomer

I'm using Fluent and NHibernate.

like image 957
Josh Avatar asked Feb 18 '10 06:02

Josh


1 Answers

You can map directly to interfaces in NHibernate, by plugging in an EmptyInterceptor during the configuration stage. The job of this interceptor would be to provide implementations to the interfaces you are defining in your mapping files.

public class ProxyInterceptor : EmptyInterceptor
{
    public ProxyInterceptor(ITypeHandler typeHandler) {
        // TypeHandler is a custom class that defines all Interface/Poco relationships
        // Should be written to match your system
    }

    // Swaps Interfaces for Implementations
    public override object Instantiate(string clazz, EntityMode entityMode, object id)
    {
        var handler = TypeHandler.GetByInterface(clazz);
        if (handler == null || !handler.Interface.IsInterface) return base.Instantiate(clazz, entityMode, id);
        var poco = handler.Poco;
        if (poco == null) return base.Instantiate(clazz, entityMode, id);

        // Return Poco for Interface
        var instance = FormatterServices.GetUninitializedObject(poco);
        SessionFactory.GetClassMetadata(clazz).SetIdentifier(instance, id, entityMode);

        return instance;
    }

}

After this, all relationships and mappings can be defined as interfaces.

public Parent : IParent {
    public int ID { get; set; }
    public string Name { get; set; }
    public IChild Child { get; set; }
}

public Child : IChild {
    public int ID { get; set; }
    public string Name { get; set; }
}

public class ParentMap : ClassMap<IParent>
{
    public ParentMap()
    {
        Id(x => x.ID).GeneratedBy.Identity().UnsavedValue(0);
        Map(x => x.Name)
    }
}   

...

This type of technique is great if you want to achieve true decoupling of your ORM, placing all configuration/mappings in a seperate project and only referencing interfaces. Your domain layer is then not being polluted with ORM, and you can then replace it at a later stage if you need to.

like image 132
Stumblor Avatar answered Sep 24 '22 19:09

Stumblor