不确定';是';nHibernate代理的行为
本文关键字:不确定 nHibernate 代理 | 更新日期: 2023-09-27 18:02:06
我有一种情况,我需要确定继承的类是否是特定的继承类,但模型中预期的类型是基类,并且它是使用nHibernate
/Fluent nHibernate
使用Table Per Concrete Class
层次结构存储的。所以我的结构看起来有点像。。
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
希望指向一种类型的数据和Measured更改(可能有其他方法可以更改数据,而不仅仅是平面数字(。因此,我将有一个对象,它只期望一个IList<Mutation>
,并将每个后续类型的Measurement
映射到它自己的特定表,与基本Measurement
类共享Identity
。到目前为止效果不错。
现在,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
}
}
仍然不起作用。它从不运行。有人能帮我吗?
这是因为Unwrap()
返回一个Type
,所以measurement.Unwrap() is Observable
将始终是false
,而measurement.Unwrap() is Type
将永远是true
。
使用运算符类型和引用相等:
if (measurement.Unwrap() == typeof(Observable)) {
// Then we know to lookup the other value.
}
Hamidi答案中的检查是不够的。一旦您在映射中添加了一些惰性属性,例如:
<property name="Description" type="StringClob" not-null="false" lazy="true"/>
Unwrap方法将失败,因为对于使用惰性属性的类型,对象始终是代理,并且检查
if (measurement.Unwrap() == typeof(Observable)) {
// Then we know to lookup the other value.
}
将失败,因为"展开"将返回代理的类型,而不是预期的类型。
我使用以下方法来检查实体类型:
public virtual Type GetEntityType()
{
var type = GetType();
// Hack to avoid problem with some types that always be proxy.
// Need re-evaluate when upgrade to NH 3.3.3
return type.Name.EndsWith("Proxy") ? type.BaseType : type;
}
public virtual bool IsOfType<T>()
{
return typeof(T).IsAssignableFrom(GetEntityType());
}
检查变为:
if (measurement.IsOfType<Observable>()) {
// Then we know to lookup the other value.
}
正如你在代码注释中看到的,这是对NH 3.1和Castle Proxy的破解:Castle Dynamic Proxy类型总是以Proxy结尾,所以我利用这个签名来检测对象是否是代理。我的项目仍然使用NH3.1,所以我不确定NH3.3需要对方法进行什么更改。