不确定“是”; nHibernate 代理的行为
我有一种情况,我需要确定继承的类是否是特定的继承类,但模型中期望的类型是基类,并且使用 nHibernate
/存储使用
。所以我的结构看起来有点像这样。每个具体类一个表
层次结构的流畅 nHibernate
class Mutation : Entity {
virtual Aspect Aspect { get; set; }
virtual Measurement Measurement { get; set; }
}
abstract class Measurement : Entity {
// does nothing on its own, really.
}
class Numeric : Measurement {
virtual int Value { get; set; }
// may have some other properties
}
class Observable : Measurement {
virtual Aspect Aspect { get; set; }
}
所以基本上,这里发生的事情是这样的。 Mutation
期望指向一种数据类型和一个测量的更改(可能有其他方法来更改数据,而不仅仅是平面数字)。因此,我将拥有一个仅需要 IList
的对象,并将每个后续类型的 Measurement
映射到其自己的特定表,共享 Identity
code> 与基 Measurement
类。到目前为止效果很好。
现在,Observable 的不同之处在于它不存储自己的值,而是再次指向另一个可能具有自己的突变和更改集的 Aspect。这个想法是,该值将始终从预期来源检索,而不是在数据库中保存为平面值。 (想要这种行为的原因超出了这个问题的范围)
那么,我的想法基本上是进行这样的评估..
foreach(var measurement in list) {
if(measurement is Observable){
// then we know to lookup the other value
}
}
那不起作用。我仍然得到 MeasurementProxy
的代理结果。但相同的代码在不使用 nHibernate 的独立 C#
应用程序中运行良好,因此我非常确信问题出在代理上。
然后,我将以下方法添加到我的基 Entity
类中...
/// <summary>
/// Unwrap the type from whatever proxy it may be
/// behind, returning the actual .NET <typeparamref name="System.Type"/>.
/// </summary>
/// <returns>
/// A pure <typeparamref name="System.Type"/> that is no longer proxied.
/// </returns>
public virtual Type Unwrap() {
return GetType();
}
现在,如果我执行 Console.WriteLine(measurement.Unwrap());
我会得到正确的类型,但同样的评价...
foreach(var measurement in list) {
if(measurement.Unwrap() is Observable){
// then we know to lookup the other value
}
}
仍然不起作用。它永远不会运行。有人可以帮我吗?
I have a situation where I need to determine whether or not an inherited class is a specific inherited class, but the type expected in the model is the base class, and it is stored using nHibernate
/Fluent nHibernate
using a Table Per Concrete Class
Hierarchy. So my structure looks a bit like this..
class Mutation : Entity {
virtual Aspect Aspect { get; set; }
virtual Measurement Measurement { get; set; }
}
abstract class Measurement : Entity {
// does nothing on its own, really.
}
class Numeric : Measurement {
virtual int Value { get; set; }
// may have some other properties
}
class Observable : Measurement {
virtual Aspect Aspect { get; set; }
}
So basically, what is going on here is this. Mutation
expects to be pointed to a type of data, and a Measured change (there could be other ways to change the data, not just flat numerics). So then I would have an object that merely expects an IList<Mutation>
and map each subsequent type of Measurement
to its own specific table, sharing the Identity
with the base Measurement
class. That works fine so far.
Now an Observable
is different in that it does not store its own value, but rather it points again to another Aspect
that may have its own set of mutations and changes. The idea is that the value will always be retrieved from the intended source, and not saved as a flat value in the database. (There is a reason for wanting this behavior that is beyond the scope of this question)
So then, my thought was basically to put in an evaluation like this ..
foreach(var measurement in list) {
if(measurement is Observable){
// then we know to lookup the other value
}
}
That didn't work. I still get the proxied result of just MeasurementProxy
. But the same code works fine in a standalone C#
application without the use of nHibernate, so I feel a great deal of confidence that the issue is with the proxy.
I then added the following method to my base Entity
class...
/// <summary>
/// Unwrap the type from whatever proxy it may be
/// behind, returning the actual .NET <typeparamref name="System.Type"/>.
/// </summary>
/// <returns>
/// A pure <typeparamref name="System.Type"/> that is no longer proxied.
/// </returns>
public virtual Type Unwrap() {
return GetType();
}
Now if I do a Console.WriteLine(measurement.Unwrap());
I get the right type, but the same evaluation ...
foreach(var measurement in list) {
if(measurement.Unwrap() is Observable){
// then we know to lookup the other value
}
}
still does not function. It never runs. Can anyone help me out here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是因为
Unwrap()
返回一个Type
,因此measurement.Unwrap() is Observable
将始终为false
,并且measurement.Unwrap() is Type
将始终为true
。请改用 typeof 运算符并引用相等性:
That's because
Unwrap()
returns aType
, someasurement.Unwrap() is Observable
will always befalse
, andmeasurement.Unwrap() is Type
would always betrue
.Use the typeof operator and reference equality instead:
哈米迪的检查答案还不够。一旦您在映射中添加了一些惰性属性,例如:
Unwrap 方法就会失败,因为对于使用惰性属性的类型,对象始终是代理,并且检查
将失败,因为 Unwrap 将返回 Proxy 类型,不是预期的类型。
我使用以下方法来检查实体类型:
并且检查变成:
正如您在代码注释中看到的,这是针对 NH 3.1 和 Castle Proxy 的 hack:Castle 动态代理类型始终以 Proxy 结尾,因此我利用此签名来检测是否对象是否是代理。我的项目仍然坚持使用 NH3.1,所以我不确定该方法需要使用 NH3.3 进行哪些更改。
The check in Hamidi answer is not enough. As soon as you add some lazy properties into your mapping, for example:
the Unwrap method will fail, because for the types that employ lazy properties, the objects are always proxy, and the check
will fail because Unwrap will return the type of Proxy, not the expected type.
I use following methods for checking entity types:
and the check becomes:
As you see in the code comment, this is a hack for NH 3.1 and Castle Proxy: Castle Dynamic Proxy types always end with Proxy, so I exploited this signature to detect if the object is proxy or not. My project is still stuck with NH3.1 so I'm not sure what changes the method will need with NH3.3.