簡體   English   中英

C#泛型:我可以約束一組沒有實現接口的類嗎?

[英]C# Generics: Can I constrain to a set of classes that don't implement an interface?

我有3個基本相同但沒有實現接口的類,因為它們都來自不同的Web服務。

例如

  • Service1.Object1
  • Service2.Object1
  • Service3.Object1

它們都具有相同的屬性,我正在編寫一些代碼,使用實現我自己的接口IObject1的中間對象將它們相互映射。

我用泛型做過這個

public static T[] CreateObject1<T>(IObject1[] properties)
  where T : class, new()
{
   //Check the type is allowed
   CheckObject1Types("CreateObject1<T>(IObject1[])", typeof(T));
   return CreateObjectArray<T>(properties);
}

private static void CheckObject1Types(string method, Type type)
{
  if (type == typeof(Service1.Object1)
  || type == typeof(Service2.Object1)
  || type == typeof(Service3.Object1)
  || type == typeof(Service1.Object1[])
  || type == typeof(Service2.Object1[])
  || type == typeof(Service3.Object1[]))
  {
     return;
  }

  throw new ArgumentException("Incorrect type passed to ServiceObjectFactory::" + method + ". Type:" + type.ToString());
}

我的客戶端代碼如下:

//properties is an array of my intermediary objects
Object1[] props = ServiceObjectFactory.CreateObject1<Object1>(properties);

我想要做的是擺脫CheckObject1Types方法並使用約束,以便在類型無效時我得到構建錯誤,因為目前我可以使用任何類型調用此方法,並且拋出ArgumentException CheckObject1Types方法。

所以我想做一些像:

public static T[] CreateObject1<T>(IObject1[] properties)
  where T : class, new(), Service1.Object1|Service2.Object1|Service3.Object1
{
   return CreateObjectArray<T>(properties);
}

有任何想法嗎?

編輯:我不想更改每個Web服務的Reference.cs文件,因為只需要一個隊友來更新Web引用和BAM! 破碎的代碼。

假設生成的類是部分的,您可以創建一個接口,然后添加另一個部分源文件,以使生成的類實現該接口。 然后您可以正常約束接口。 無需更改實際生成的代碼:)

在C#中不可能像你想要的那樣以“OR”方式約束到類列表。 (事實上​​,我甚至不確定它在IL中是否合法。)

您唯一的選擇是繼續使用checktypes樣式函數。 如果您擁有不同Web服務的代碼,您還可以實現“sentinel”接口並將其用作約束。 我知道根據框架設計指南不推薦使用哨兵界面,但它們偶爾會有它們的用途(這是其中之一)。

正如Jon指出的那樣,您可以使用prtial類來實現通用接口。 如果您的References.cs實現了一個類:

namespace TestServices
{
   internal partial class Service1SoapClient : System.ServiceModel.ClientBase<T>, K
   {
   }
}

然后,您將在同一名稱空間中創建另一個部分類(稱為References.CommonInterface.cs),它可以存在於項目的任何位置,具有以下內容:

namespace TestServices
{
   internal interface ICommon
   {
   }

   internal partial class Service1SoapClient : ICommonInterface
   {
   }
}

我會寫一個轉換器類,它將你的三個對象中的任何一個帶入一個支持你想要的接口的新對象。 此外,我會使用反射,因此您不必手動鍵入所有分配(除非它是一個小對象,並且預計不會改變太多)。

使用Reflection還可以保證您希望確保對象實現新Interfaced對象實現的任何屬性,否則當您期望的屬性未實現時,您可能會拋出錯誤。

如果您從Web服務中提取這些對象,則可以對所使用的類定義進行控制。 它們不僅僅是憑空出現(即使你最初有代碼生成器或visual studio創建它們)。 在某些地方仍然有一個類文件必須使用應用程序進行編譯,並且您應該能夠將這個公共接口添加到這些類定義中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM