2010-12-13 88 views
0

J'essaie le FluentNHibernate AutoPersistenceModel pour la première fois. C'était très simple d'avoir un exemple de base qui fonctionne, mais j'ai un problème pour le faire correspondre à la façon dont je travaille. Je travaille normalement aux interfaces de sorte que mes entités implémentent toutes une interface et référencent toutes les entités liées par leur interface, et non leur type concret. Étant donné les classes suivantes:FluentNHibernate AutoPersistenceModel avec références d'interface

public Interface IFoo { } 

public Interface IBar { IFoo Foo { get; set; } } 

public Class Foo : IFoo { } 

public Class Bar : IBar 
{ 
    public IFoo Foo { get; set; } 
} 

j'aurais la correspondance suivante:

public class BarMapping : ClassMap<Bar> 
{ 
    public AnswerMapping() 
    { 
     References<Foo>(x => x.Foo).Column("FooId").Cascade.None(); 
    } 
} 

Comment pourrais-je obtenir la même chose avec le AutoPersistenceModel? J'ai jeté un bref coup d'œil sur les conventions et le constructeur de ReferenceConvention, mais sans documentation ni exemples, j'ai pataugé.

EDIT

Je suis maintenant tourné ce long avec mon autre SO post sur la cartographie de la collecte des interfaces dans un billet de blog: http://bronumski.blogspot.com/2011/01/making-fluent-nhibernate-automapper.html

Répondre

1

Après un peu de creuser autour, je suis venu avec une solution . Il y a une interface IReferenceConvention que j'ai vu utilisée dans d'autres exemples mais qui ne couvre pas ce scénario. En implémentant l'interface et en faisant une convention personnalisée, j'ai pu réaliser la même chose avec AutoPersistenceModel que j'étais avec ClassMap.

public class ReferenceConvention : IReferenceConvention 
{ 
    public void Apply(IManyToOneInstance instance) 
    { 
     Type instanceType = instance.Class.GetUnderlyingSystemType(); 
     if (instanceType == typeof(IFoo)) 
     { 
      instance.CustomClass<Foo>(); 
     } 

     instance.Cascade.All(); 
    } 
} 

Une approche plus générique pourrait être:

public class ReferenceConvention : IReferenceConvention 
{ 
    public void Apply(IManyToOneInstance instance) 
    { 
     Type instanceType = instance.Class.GetUnderlyingSystemType(); 

     if (instanceType.IsInterface) 
     { 
      // Assuming that the type starts with an I get the name of the concrete class 
      string className = instanceType.Name.Substring(1); 

      instance.CustomClass(instanceType.Assembly.GetType(
       instanceType.FullName.Replace(instanceType.Name, className))); 
     } 

     instance.Cascade.All(); 
    } 
} 

Il y a aussi une ReferenceConventionBuilder que je ne l'ai pas regardé encore, mais cela pourrait être une solution plus propre.