我正在使用NHibernate的程序,我有以下问题: 我的一些类的成员是基本上只定义一些处理程序的类的实例。
例如
public class Foo
{
virtual public ResultHandler handler {get; set;}
virtual void Bar()
{
...
handler.HandleResult(...);
}
}
public abstract class ResultHandler
{
abstract public void HandleResult(...);
}
public class ResultPrint : ResultHandler
{
override public void HandleResult(...)
{
...
}
}
public class ResultExport : ResultHandler
{
override public void HandleResult(...)
{
...
}
}
现在ResultPrint和ResultExport没有任何成员,因此它们不必映射到数据库中的表,但是当我存储/检索Foo的实例时,我想以某种方式存储&加载成员“handler”。
我可以将类名存储在字符串中并使用反射来加载它(但是在重命名类的情况下这会不稳定,这会浪费数据库中的空间)。存储单个字节就足够了 - 但我如何告诉NHibernate呢?
我能想到的最好的方法是映射像
这样的虚拟成员virtual public byte HandlerClass
{
get
{
if(handler == null)
return 0;
switch(handler.GetType())
{
case typeof(ResultPrint):
return 1;
...
}
}
set
{
switch(value)
{
case 0:
handler = null;
break;
case 1:
handler = new ResultPrint();
break;
...
}
}
}
但对于应该是常见用例的事情来说,这是非常复杂的...... 必须有一种“干净”的方式让NHibernate自己做到这一点。 任何人都可以帮助我吗?
亲切的问候
AlgoMan
编辑:我正在使用基于XML的映射btw。
答案 0 :(得分:1)
我认为,虽然具体类ResultPrint和ResultExport不是任何实例成员,但抽象类ResultHandler有一些成员要保存在数据库中。
您可以将ResultHandler,ResultPrint和ResultExport映射到一个带有鉴别器列的表中。
例如:
<class name="ResultHandler" abstract="true" table="ResultHandlers">
<id name="Id">
<generator class="identity"/> <!-- WHATEVER IS YOUR IDENTITY HERE! -->
</id>
<discriminator column="type" not-null="true" type="System.String"/>
<subclass name="ResultPrint" discriminator-value="print">
</subclass>
<subclass name="ResultExport" discriminator-value="export">
</subclass>
</class>
除了普通列之外,ResultHandlers表还必须有一个附加列来映射子类,在上面的映射示例中,这些列是“类型”列。
当子类为ResultPrint时,当这些类中的一个对象首次保存在数据库中时,此列将自动填充为ResultExport的“print”或“export”。
答案 1 :(得分:0)
正如您所指出的,您的ResultHandler
个对象不需要保留。
事实上,这似乎并不像NH问题。
只需保留一些允许重建正确ResultHandler的数据来保持你的Foo状态对我来说似乎是正确的方法。
唯一的问题是ResultHandler
不应该处理从一个字节构建Foo
的逻辑。它应该属于一个专用类,并且可以重用(如果你愿意的话,也许你可以使用一些依赖注入机制)
这会导致类似:
private byte _handlerClass;
virtual public byte HandlerClass{
get{return _handlerClass; }
set{_handlerClass = value; _handler =null;}
}
private ResultHandler _handler;
public virtual ResultHandler Handler
{
get{
return _handler ?? (_handler = HandlerServiceLocator.GetHandler(HandlerClass));
}
}
然后,从一个字节构建ResultHandler
的专用类:
public class HandlerServiceLocator
{
public static ResultHandler GetHandler(byte value)
{
switch(value)
{
case 0:
return null;
case 1:
return new ResultPrint();
...
}
return null;
}
}