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

C# NHibernate-映射运行时定义类型的属性,c#,generics,nhibernate,fluent-nhibernate,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 DungeonGeom

好的,我需要创建两个表,除了一个字段外,这些表几乎相同

我的模型大致如下所示:

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...
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 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();
}
所以,这里所有的模型基本上只有Attributes属性不同,所以我认为有一种方法可以将所有的东西统一到一个泛型中?班级

我可以想出两种方法来实现这一点:

创建一个通用类GeometryModel,如下所示:

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

    public virtual TAttributes Attributes { get; set; }
}
问题是我没有指定流畅的映射。映射也应该以这种方式实现类映射,因此不可能用NHibernate实例化它

使属性属性成为动态的。它也不起作用,因为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...
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 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();
}
我的映射如下所示:

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...
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 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();
}
我编写了以下扩展方法:

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;
}
我是这样用的:

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...
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 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();
}