NHibernate - 映射运行时定义类型的 属性
NHibernate - map a property of a runtime-defined type
好的,所以我需要创建几个表,除了一个字段外,它们几乎完全相同。
我的模型大致如下所示:
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
属性 不同,所以我认为可能有一种方法可以将所有内容统一为一个(通用的?)class .
我可以想出两种实现方法:
制作一个通用的 class 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 实例化它。
制作Attributes
属性dynamic
。它也不起作用,因为 NHibernate 在创建 ClassMap<>
.
时将 dynamic
属性视为 object
有什么解决办法吗?
我最终通过运行时 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();
}
好的,所以我需要创建几个表,除了一个字段外,它们几乎完全相同。
我的模型大致如下所示:
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
属性 不同,所以我认为可能有一种方法可以将所有内容统一为一个(通用的?)class .
我可以想出两种实现方法:
制作一个通用的 class
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 实例化它。制作
Attributes
属性dynamic
。它也不起作用,因为 NHibernate 在创建ClassMap<>
. 时将
dynamic
属性视为 object
有什么解决办法吗?
我最终通过运行时 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();
}