2011-09-15 48 views
3

我有以下一組接口和類。混淆與多接口實現

public interface IValidatableObject 
{ 
    List<string> ValidationErrors { get; } 
    bool Validate(); 
} 

public class ValidatableObject : IValidatableObject 
{ 
    public List<string>ValidationErrors { get; } 
    public bool Validate() 
    { 
     //dostuff 
    } 
} 

public interface IDeviceDataObject 
{ 
    int Id { get; set; } 
    string Name { get; set; } 
} 

public class DeviceDataObject : ValidatableObject, IDeviceDataObject 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

public class DeviceService 
{ 
    public bool ValidateDevice(IDeviceDataObject device) 
    { 
     return device.Validate(); // This throws a compiler error 
    } 
} 

在上面的服務操作ValidateDevice的問題是,編譯器不能解析device.Validate(),因爲IDeviceDataObject沒有實現IValidatableObject接口。

我的問題是,是否正確更改IValidatableObject以實施IValidatableObject。我有點不確定這是否是好的做法,因爲我看到它的方式,DeviceDataObject實施IValidatableObject兩次 - 一次通過ValidatableObject,一次通過IDeviceDataObject。任何人都可以幫我解決這個問題嗎?

public interface IDeviceDataObject : IValidatableObject 
{ 
    int Id { get; set; } 
    string Name { get; set; } 
} 
+1

爲什麼你的ValidateDevice簽名看起來像「public bool ValidateDevice(IValidatableObject someobj)'?不是什麼表達驗證方法的功能:它需要一些可驗證的功能。其他一切都可以保持原樣。 –

+0

公平的電話。但是如果它是一個CreateDevice方法需要知道它是一個傳入的IDeviceDataObject,但它仍然需要具有IValidatableObject功能呢? – Chris

+0

因此 - 因爲我不知道這裏的大圖 - 所有的IDeviceDataObjects應該可驗證嗎?如果是,則讓''IDeviceDataObject''從''IValidatableObject''繼承。如果沒有,那麼這是無法解決的。它有時真的很簡單:它只是一個在語義上有意義的問題。然後將它翻譯成代碼是一個相當簡單的步驟。 –

回答

1

我可能在這裏理解錯誤(並且我不知道你的類架構作爲一個整體),但爲什麼你的ValidateDevice方法沒有獲取validatable對象呢?簽名會看起來像:

public bool ValidateDevice(IValidatableObject someobj) 

心不是什麼表示,做驗證方法的功能:它需要的東西是可驗證。一切可能(從IValidatableObject即別讓IDeviceDataObject繼承,你可能想表達的,並不是每一個devicedataobject也可驗證例如)留事情是這樣的

的第二種方式,如果你想確保ValidateDevice只需要對象實現IDeviceDataObject,你也可以嘗試跨投地IValidatableObject

public bool ValidateDevice(IDeviceDataObject someobj) 
{ 
    if(someobj is IValidatableObject) 
    { 
     return ((IValidatableObject)device).Validate(); 
    } 
    return //something that makes sense if the device is not validatable 
} 
0

你可以讓你的ValidateDevice方法一般把它留到調用者在實現的接口,右邊的組合對象實例傳遞 - 這將讓你的界面保持獨立,仍然執行類型安全:

public class DeviceService 
{ 
    public bool ValidateDevice<T>(T device) where T: IDeviceDataObject, IValidatableObject 
    { 
     return device.Validate(); 
    } 
} 
1

你可以簡單地轉換爲IValidatableObject。

public class DeviceService 
{ 
    public bool ValidateDevice(IDeviceDataObject device) 
    { 
     IValidatableObject v = device as IValidatableObject; 

     if (v != null) 
      return device.Validate(); 
     return false; 
    } 
} 
+0

但是所有處於有效狀態但不執行「IValidatableObject」的設備都將無法通過驗證。 – Eranga

+0

@Eranga - 而且?他們可以通知有效的唯一方法是實現IValidatableObject。我沒有看到問題。 –

+0

API正在說謊。我希望'ValidateDevice'方法可以根據'IDeviceDataObject'合同進行驗證。我必須通過'ValidateDevice'的實現來了解我也必須實現'IValidatableObject'。 – Eranga

0

我推斷了很多名字,但在我看來,好像IDeviceDataObjectIValidatableObject是分開的想法。看起來合理的是,您可以擁有實現IDeviceDataObjectIValidatableObject或兩者(是?)的對象。如果這是真的,那麼在兩個接口之間沒有「是」關係(你不會假設IDeviceDataObjectIValidatableObject),所以從另一個接口繼承一個接口似乎是錯誤的。

至於你的ValidateDevice方法(或任何方法) - 如果它將使用參數作爲IDeviceDataObject,參數應該是該類型。如果它將使用參數IValidatableObject,則參數應爲,即類型。如果可能同時使用這兩個功能,則可能需要傳入較不具體的類型,然後執行運行時檢查(使用C#'is'或'as')來查看對象是否支持特定的接口。