2013-01-23 25 views
6

我需要一個小模式的方向。新的C#。我不能控制的兩個第三方類的通用接口。外部多態性?

我正在使用包裝Web服務的第三方開發工具包。我處理的有兩個特定類,雖然比較相似,但在devkit中有兩個不同的名稱空間,沒有共同的基類。但是我希望程序針對它們的通用界面。我隨意地把一個實現包裝在包裝中的實現扔到了一起,但我確信它不是最有效的方法,因爲不斷的類型轉換。

我一直在挖掘關於適配器,接口,擴展方法等的文章。但是我的運行時間很短,所以如果我能夠在一個方向推動,將不勝感激。

using ThirdParty.TypeA.Employee; 
using ThirdParty.TypeB.Employee; 

public class Employee 
{ 
    private object genericEmployee; 

    private EmployeeType empType; 

    public enum EmployeeType 
    { 
      TypeA = 0; 
      TypeB = 1; 
    } 

    public Employee(Object employee, EmployeeType type) 
    { 
     genericEmployee = employee; 
     empType = type; 
    } 

    public String Name 
    { 
     if (empType == EmployeeType.TypeA) 
      return (ThirdParty.TypeA.Employee)genericEmployee.Name; 
     else 
      return (ThirdParty.TypeB.Employee)genericEmployee.Name; 
    } 

    public String Age 
    { 
     if (empType == EmployeeType.TypeA) 
      return (ThirdParty.TypeA.Employee)genericEmployee.Age; 
     else 
      return (ThirdParty.TypeB.Employee)genericEmployee.Age; 
    } 
} 

版本2:

class EmployeeTypeAAdapter : TypeA, IEmployeeAdapter 
{ 
    TypeA _employee; 
    public EmployeeTypeAAdapter(TypeA employee) 
    { 
     _employee = employee 
    } 

    public String Name 
    { 
     get { return _employee.Name; } 
     set { _employee.Name = value; } 
    } 

     public String Balance 
     { 
     get 
     { 
      if (_employee.Balance != null) 
      { 
       decimal c = _employee.Balance.Amount; 
       return String.Format("{0:C}", c); 
      } 
      else 
      { 
       return ""; 
      } 
      } 
     } 

     //... 
} 

class EmployeeTypeBAdapter : TypeB, IEmployeeAdapter 
{ 
    TypeB _employee; 
    public EmployeeTypeAAdapter(TypeB employee) 
    { 
     _employee = employee 
    } 

    public String Name 
    { 
     get { return _employee.Name; } 
     set { _employee.Name = value; } 
    } 

     public String Balance 
     { 
     get 
     { 
      if (_employee.Balance != null) 
      { 
       decimal c = _employee.Balance.Amount; 
       return String.Format("{0:C}", c); 
      } 
      else 
      { 
       return ""; 
      } 
      } 
     } 

    //.... 
} 
+0

TypeA和TypeB是公共的還是衆所周知的,我的意思是你真的需要引入enum嗎?你可以採用通用的方式。 – abatishchev

+0

TypeA和TypeB的類型是什麼,這些類是如何聲明的?同樣的屬性集合,沒有基類?所以你可以通過'object'來概括它們? – abatishchev

+0

第三方庫中沒有基類。枚舉只是我創建的一個便利屬性,用於避免每次訪問屬性時都不得不使用TypeOf或IS來確定對象的類型(TypeA或TypeB)。 – RyanMac

回答

8

試試這個辦法:

public interface IEmployeeAdapter 
{ 
    string Age { get; set; } 
    string Name { get; set; } 
} 

class EmployeeTypeAAdapter : TypeA, IEmployeeAdapter 
{ 
    public EmployeeTypeAAdapter(TypeA employee) { } 
} 

class EmployeeTypeBAdapter : TypeB, IEmployeeAdapter 
{ 
    public EmployeeTypeBAdapter(TypeB employee) { } 
} 

public static class EmployeeAdapterFactory 
{ 
    public static IEmployeeAdapter CreateAdapter(object employee, EmployeeType type) 
    { 
     switch (type) 
     { 
      case EmployeeType.TypeA: return new EmployeeTypeAAdapter((TypeA)employee); 
      case EmployeeType.TypeB: return new EmployeeTypeBAdapter((TypeB)employee); 
     } 
    } 

    // or without enum 

    public static IEmployeeAdapter CreateAdapter(object employee) 
    { 
     if (employee is TypeA) return new EmployeeTypeAAdapter((TypeA)employee); 
     if (employee is TypeB) return new EmployeeTypeABdapter((TypeB)employee); 
    } 

    // or better introduce sort of type map 
} 

另一個合適的名字是EmployeeProxy,根據您的喜好。

+0

然後我會返回上面詳述的適配器中的屬性嗎?考慮到兩個對象(TypeA和TypeB)是如何99%相同(可能有30個屬性/方法中的一個或兩個具有不同的名稱),並且只有真正的差異類型(一個是ThirdPartyAdaptor.TypeA.Employee類型另一個是ThirdPartyAdaptor.TypeB.Employee),這似乎會創建幾乎重複的類。見上文第二部分。 – RyanMac

+0

@RyanMac:那麼困難是什麼?抱歉不要跟着你。您將所有共享屬性放入界面中,它將自動實施。如果屬性名稱在底層類型和接口中不同,則可以「幫助」正確地實現/匹配它。 – abatishchev

+0

@RyanMac:你也可以引入一個包含共享屬性和其他幫助方法的抽象基類 – abatishchev

2

你正在做的事情被稱爲Duck typing。您可以使用適配器類和共享接口來執行此操作,但手動創建這些適配器需要大量重複的膠水代碼。一種可以避免編寫膠水代碼的方法是動態構建適配器類型。你可以通過IL Emit自己做這件事(如果你以前從來沒有機會玩過它,這是一個有價值的練習,儘管可以考慮很多邊界情況。)如果你只是想讓它工作,然而,你可以檢查出this project作爲一個開始的地方。也可以使用C#的'動態'類型(並且在幕後執行一些相同的代碼生成),但是它沒有給你一個可以傳遞給非動態代碼的引用,就好像它是一個接口類型。