2011-07-15 57 views
1

我有一種情況需要確定繼承的類是否是特定的繼承類,但是模型中預期的類型是基類,並且它是使用nHibernate/Fluent nHibernate使用Table Per Concrete Class層次結構。所以我的結構看起來有點像這樣..不確定nHibernate代理的'is'行爲

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<Mutation>並映射每個後續類型的Measurement它自己的具體表,共享Identity與基類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 
    } 
} 

仍然不起作用。它從不運行。有人可以幫我從這裏出去嗎?

回答

2

這是因爲Unwrap()返回Type,所以measurement.Unwrap() is Observable永遠是false,並且measurement.Unwrap() is Type將永遠是true

使用typeof操作和參考平等,而不是:

if (measurement.Unwrap() == typeof(Observable)) { 
    // Then we know to lookup the other value. 
} 
+0

這麼簡單,但我從來沒有想過嘗試。謝謝,這確實是錯誤的。這是一種合理的方法來嘗試形成基於類類型的引用和行爲嗎?或者我完全錯過了正確的答案? – Ciel

+0

Stack Overflow讓我在7分鐘內接受你的答案。 – Ciel

+0

@Ciel,謝謝。不幸的是,我對NHibernate不夠熟悉,不知道這是否是解決根本問題的最佳方法......它應該可以工作,所以它可能是一個合理的方法:) –

0

在哈米迪答案的檢查是不夠的。只要你添加一些懶惰的屬性到您的映射,例如:

<property name="Description" type="StringClob" not-null="false" lazy="true"/> 

的展開方法將失敗,因爲對於採用延遲屬性的類型,對象總是代理,並檢查

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動態代理服務器類型總是以代理服務器結束,所以我利用此簽名來檢測對象是否爲代理服務器。我的項目仍然停留在NH3.1上,所以我不確定NH3.3需要什麼樣的方法改變。