2016-06-22 94 views
1

上下文類:使用實現接口

我想有兩個庫 - 一個是傳統的一個使用現有的實現和兩個是一些與驗證等過程的一個更精簡的版本。另外,要長期清除多餘的數據。

我在非傳統圖書館兩個接口:

public interface IMyAttribute 
{ 
    int Id { get; set; } 
    dynamic Value { get; set; } // if Value can be of different types, is there a better way? 

    bool IsValid(); 
} 

public IMyData 
{ 
    List<IMyAttribute> data { get; set; }; 

    void SetProperties(); 
    bool IsValid(); 
} 

我設置了傳統圖書館參考「新」庫。對於IMyAttribute的傳統實現,IsValid返回true,因爲目前沒有現有的驗證。這將從表中提取數據,該表將具有AttributeValue,AttributeValueNumber或AttributeValueDate字段集,並應相應地執行(string,double,DateTime),因此使用動態Value。對於IMyData的傳統實現,我已經向對象添加了屬性,並且SetProperties設置了該實例的屬性。

我的問題是,我基本上鍊接到它似乎的接口。或者說,我試圖這樣做,我似乎只能鏈接到界面。我的目標是「我將擁有這些參數和這些回報的方法,或多或少」。但我想這樣做,遇到了問題:

public class MyLegacyAttribute : IMyAttribute 
{ 
    //implementing items from interface plus other methods and properties 
} 

public class MyLegacyData : IMyData 
{ 
    ... 
    List<MyLegacyAttribute> data { get; set; } 
    ... 
} 

有沒有做這種方式,它可將合同性質還是我處理它不正確的方法是什麼?我試圖修改IMyData到:

List<T> data where T : IMyAttribute { get; set; } 
List<T> data { get; set; } where T : IMyAttribute // didn't think this would work, but gave it a shot. 

無濟於事。

回答

1

目前尚不清楚您的具體問題在這裏。如果你提供一個很好的Minimal, Complete, and Verifiable code example,它會幫助你清楚你想要做什麼,以及一個精確的描述什麼代碼現在正在做什麼,以及這是如何不同於你想要做的。非常具體。

與此同時,我可以提供一些想法,可能會或可能不會幫助。

首先,不要在接口中使用dynamic。沒有意義。如果你不能使接口是通用的,那麼只需使用object。如果它真的需要該功能,則使用該接口的代碼可以將object指定爲dynamic。更有可能的是,它也不應該使用dynamic,而應該只是以這種方式投射到已知類型和訪問成員。

儘管如此,您可以使接口通用。即:

public interface IMyAttribute<T> 
{ 
    int Id { get; set; } 
    T Value { get; set; } 

    bool IsValid(); 
} 

當然,做這樣將導致所有使用具有也被感知類型的接口的代碼。但從長遠來看,這將會非常好,因爲您可以避免投射問題,並且可以進行編譯時類型檢查。

至於有關MyLegacyData類型,而你不是這個很清楚的問題,看來你正在運行成List<MyLegacyAttribute>相同或甚至List<IMyAttribute>兼容,即使MyLegacyAttribute實現問題IMyAttribute。原因應該很清楚:MyLegacyData對象可以被任何其他代碼視爲IMyData,然後該代碼可以始終訪問data元素(應該將其拼寫爲Data)作爲List<IMyAttribute>。然後,代碼可以嘗試將IMyAttribute的一些實現添加到MyLegacyAttribute以外的列表中,MyLegacyAttribute實際類型爲MyLegacyData

編譯器不會讓你這樣做,這是很好的理由。

如果您可以使IMyData成爲通用接口,那麼您一般也可以定義MyLegacyData。例如:

public IMyData<T> where T : IMyAttribute 
{ 
    List<T> data { get; set; }; 

    void SetProperties(); 
    bool IsValid(); 
} 

public class MyLegacyData<T> : IMyData<T> where T : IMyAttribute 
{ 
    ... 
    List<T> data { get; set; } 
    ... 
} 

您可以將二者結合起來的想法是這樣的:

public interface IMyAttribute<T> 
{ 
    int Id { get; set; } 
    T Value { get; set; } 

    bool IsValid(); 
} 

public IMyData<TData, TValue> where TData : IMyAttribute<TValue> 
{ 
    List<TData> data { get; set; }; 

    void SetProperties(); 
    bool IsValid(); 
} 

public class MyLegacyData<TData, TValue> : IMyData<TData, TValue> 
    where TData : IMyAttribute<TValue> 
{ 
    ... 
    List<TData> data { get; set; } 
    ... 
} 

如果你想出於某種原因非通用版本,那麼你仍然可以創建一個子類的那:

public class MyNongenericLegacyData : MyLegacyData<MyLegacyAttribute> 
{ } 

或者,如果它只是不必鍵入全名的時候,你可以別名類型:

using MyNongenericLegacyData = MyNamespace.MyLegacyData<MyLegacyAttribute>; 

以上可能會完全解決您的問題。如果是這樣,很好。如果不是,請改善問題,以便更清楚地詢問你的問題。

+0

對不起,我沒有指出問題(我試圖更好地實現接口等與野生西部一切)如此表達,雖然嘗試嘗試,但感覺有點困難。這就是說,「如果你可以讓IMyData成爲一個通用的接口...」,並且基本上是我試圖做的東西。並且感謝您爲接口和泛型提供了大量的燈光,因爲它將它們帶到一起。 – Robert

+0

我有這樣一個問題:如果我有MyIntegerAttribute(MIA),MyStringAttribute(MSA)和MyDateTimeAttribute(MDTA)全部實現IMyAttribute (T分別爲int,string和DateTime),有沒有辦法單個MyLegacyData其中Data屬性是各種MIA,MSA和MDTA的集合?或者我應該回到之前提到的對象值(儘管這會影響將來的核心數據類型的任何比較邏輯等)? – Robert

+0

@Robert:你不能混合/匹配不同類型而不刪除類型。有很多種方法可以做到這一點,但並非所有這些方法都需要放棄通用的'IMyAttribute '類型,但至少「IMyData」實現將不得不放棄類型信息。例如,如果你可以'IMyAttribute '爲只讀,這樣'Value'屬性只有一個getter,那麼泛型類型方差將允許'MyLegacyData ,object >>'即使單個項目在事實更具體。否則,你將不得不犧牲某種類型的安全性。 –