2017-02-01 56 views
0

好的,所以我需要創建幾個表,除了一個字段外,它們需要幾乎相同。NHibernate - 映射運行時定義類型的屬性

我的模型將大致是這樣的:

class HouseGeometryModel 
{ 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    //More fields... 

    public virtual HouseAttributes Attributes { get; set; } 
} 

class DungeonGeometryModel 
{ 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    //More fields, all identical to HouseGeometryModel... 

    public virtual DungeonAttributes Attributes { get; set; } 
} 

class FortressGeometryModel 
{ 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    //More fields, all identical to HouseGeometryModel... 

    public virtual FortressAttributes Attributes { get; set; } 
} 

//More models... 

所以,基本上只有Attributes財產所有型號之間的區別在這裏,所以我想有可能是來統一一切都變成一個單一的(通用的方式? )類。

我可以想出兩種方式來實現這一點:

  1. 做一個泛型類GeometryModel<TAttributes>這將是這樣的:

    class GeometryModel<TAttributes> 
    { 
        public virtual int Id { get; set; } 
        public virtual string Name { get; set; } 
        //More fields... 
    
        public virtual TAttributes Attributes { get; set; } 
    } 
    

    這樣做的問題是,我不能指定流利的映射。映射也應該以這種方式變得通用(實現ClassMap<GeometryModel<TAttributes>>),因此不可能用NHibernate實例化它。

  2. 使Attributes財產dynamic。它不起作用,因爲NHibernate在創建ClassMap<>時將dynamic屬性視爲object

有沒有解決方法?

回答

0

我結束了它與運行時ClassMap<>綁定通用的方式。

我的模型看起來是這樣的:

class GeometryModel<TAttributes> 
{ 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    //More fields... 

    public virtual TAttributes Attributes { get; set; } 
} 

我的映射是這樣的:

class GeometryModelMap<TAttributes> : ClassMap<GeometryModel<TAttributes>> 
{ 
    public GeometryModelMap() 
    { 
     Id(t => t.Id).GeneratedBy.Increment(); 
     Map(t => t.Name); 
     //More mappings... 
     References(t => t.Attributes); 
    } 
} 

我寫了下面的擴展方法:

private static FluentMappingsContainer AddGenericMappings(this FluentMappingsContainer container, Type genericType, IEnumerable<Type> genericArgs) 
{ 
    foreach (var arg in genericArgs) 
    { 
     var newType = genericType.MakeGenericType(arg); 
     container.Add(newType); 
    } 
    return container; 
} 

而且我使用它像這樣:

private static ISessionFactory CreateSessionFactory(string path) 
{ 
    return Fluently.Configure() 
        .Database(SQLiteConfiguration.Standard.UsingFile(path)) 
        .Mappings(m => m.FluentMappings 
        .AddFromAssembly(Assembly.GetExecutingAssembly()) 
        .AddGenericMappings(typeof(GeometryModelMap<>), new[] { typeof(HouseAttributes), typeof(DungeonAttributes), typeof(FortressAttributes) } ) 
      ) 
      .ExposeConfiguration(config => BuildSchema(config, path)) 
      .BuildSessionFactory(); 
}