2008-11-19 71 views
2

假設我有一個.NET程序集A,它使用反射來加載程序集B和C(也稱爲.NET)。這兩個程序集都實現了許多大型接口(兩者都相同)。當在A中調用一個方法時,它會嘗試讓B完成這項工作。但是,B是不可靠的,可能會拋出異常。現在A有兩種模式,一種是將例外傳播給A的調用者,另一種是在更穩定(但性能較低)的C上調用匹配方法的模式。是否有更好的方式(少代碼)來實現這個方案比包裝所有方法B在所有B的接口的巨大實現中暴露出來的東西,現在只包含每個帶有代碼的調用,如下所示?程序集B和C不知道所選錯誤處理方法的任何內容,因此它們不能實現邏輯。大接口的統一錯誤處理

public class BErrorWrapper : I1, I2, I3{ 
    ... 
    public int DoSomeWork(int num){ 
     if (FailWithExceptions) 
     { 
     try 
     { 
      return B.DoSomeWork(num); 
     } 
     catch(MyLibException e) 
     { 
      return C.DoSomeWOrk(num); 
     } 
     } 
     else 
     { 
     return B.DoSomeWork(num); 
     } 
    } 
    ... 
} 

回答

2

你可以做到這一點,這樣可以節省一些重複:

public class BErrorWrapper : I1, I2, I3{ 
    ... 
    public int DoSomeWork(int num){ 
     try 
     { 
     return B.DoSomeWork(num); 
     } 
     catch(MyLibException e) 
     { 
     if (FailWithExceptions) throw; 
     return C.DoSomeWOrk(num); 
     } 
    } 
    ... 
} 
1

嗯...節省一些代碼,你可以通過代表包最常見的簽名,像下面(注意我已經只包括核心位,以保持它清楚 - 但你可以添加你的平凡FailWithExceptions東西):通過

static void TryWithFallback<T>(Action<T> primary, Action<T> fallback, T arg) 
    { 
     try 
     { 
      primary(arg); 
     } 
     catch // add your other regular code here... 
     { 
      fallback(arg); 
     } 
    } 

然後你就可以重新使用這種方法的實現:

TryWithFallback(b.DoSomeWork, c.DoSomeWork, num); 

很明顯,你可以添加一些簽名相關的代碼,如:

static TResult TryWithFallback<T, TResult>(Func<T, TResult> primary, Func<T, TResult> fallback, T arg) 
    { 
     try 
     { 
      return primary(arg); 
     } 
     catch 
     { 
      return fallback(arg); 
     } 
    } 
1

我建議你看一下使用反射和System.CodeDom來生成代碼。最近我有一個類似的問題,當我試圖編寫一個COM互操作程序集的包裝器時,它有一個非常大的接口,它帶有許多方法,這些方法的簽名包含了我不想在客戶端使用但我可以使用的參數類型輕鬆轉換爲我在客戶端需要的類型。它們也是'ref'參數,可以使客戶端代碼更加冗長。這些方法具有不同數量的參數,並且我想在客戶端展示有意義的名稱。

爲包含A和B實例的成員的包裝器編寫一個基類。編寫生成派生包裝類的代碼生成類。然後,代碼生成應該遍歷包裝器應該實現的每個接口的方法,並添加一個方法和方法體,該方法和方法體具有適當的代碼,以便在所需的錯誤處理構造中調用A和B.您爲調用A和B而生成的代碼將取決於您調用的方法的簽名,但通過迭代正在生成或調用的方法的參數並不難實現。

我可以發佈我的代碼,但由於我做的事情稍有不同,我認爲你最好回到MSDN或其他公開示例。我只能說,我發現這個令人驚訝的直接和強大。

我建議你檢查你的代碼生成代碼,而不是生成的代碼,並運行代碼生成作爲你的構建的一部分。