NHibernate - 映射运行时定义类型的属性

时间:2017-02-01 15:24:28

标签: c# generics nhibernate fluent-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在创建dynamic时将object属性视为ClassMap<>,因此无法正常工作。

  3. 这有什么解决方案吗?

1 个答案:

答案 0 :(得分: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();
}