2008-12-29 103 views
0

在我的web應用程序中,我使用了來自同一提供程序的幾個asmx(Web服務),它們有一個用於此目的,其他用於此目的,但都需要SOAP Header與認證。在C#中使用DS創建一個「all-in-one」函數

這是簡單的添加驗證:

public static SoCredentialsHeader AttachCredentialHeader() 
{ 
    SoCredentialsHeader ch = new SoCredentialsHeader(); 
    ch.AuthenticationType = SoAuthenticationType.CRM5; 
    ch.UserId = "myUsername"; 
    ch.Secret = apUtilities.CalculateCredentialsSecret(
     SoAuthenticationType.CRM5, apUtilities.GetDays(), "myUsername", "myPassword"); 
    return ch; 
} 

問題是這樣的SoCredentialsHeader到來(偏差)從ONE web服務,我需要將相同的代碼添加到其他人,如:

public static wsContact.SoCredentialsHeader AttachContactCredentialHeader() 
{ 
    wsContact.SoCredentialsHeader ch = new wsContact.SoCredentialsHeader(); 
    ch.AuthenticationType = wsContact.SoAuthenticationType.CRM5; 
    ch.UserId = "myUsername"; 
    ch.Secret = apUtilities.CalculateCredentialsSecret(
     wsContact.SoAuthenticationType.CRM5, apUtilities.GetDays(), "myUsername", "myPassword"); 
    return ch; 
} 

public static wsDiary.SoCredentialsHeader AttachDiaryCredentialHeader() 
{ 
    wsDiary.SoCredentialsHeader ch = new wsDiary.SoCredentialsHeader(); 
    ch.AuthenticationType = wsDiary.SoAuthenticationType.CRM5; 
    ch.UserId = "myUsername"; 
    ch.Secret = apUtilities.CalculateCredentialsSecret(
     wsDiary.SoAuthenticationType.CRM5, apUtilities.GetDays(), "myUsername", "myPassword"); 
    return ch; 
} 

有沒有一種方法來實現設計模式,以便只使用一個功能但適合所有web服務?

有時我看到T字母,這是一種情況嗎?如果是的話,我該如何完成這樣的功能?

P.S.我可以通過枚舉並使用開關來檢查枚舉名稱並應用正確的Header,但是每次我需要添加新的WebService時,我需要添加枚舉和代碼,我正在爲此搜索高級技術。

謝謝。

回答

3

創建一個名爲whatever.tt文件(訣竅是.TT擴展名)在您與解決方案的任何地方並粘貼以下代碼:

using System; 

namespace Whatever 
{ 
    public static class Howdy 
    { 
<# 
    string[] webServices = new string[] {"wsContact", "wsDiary"}; 
    foreach (string wsName in webServices) 
    { 
#> 
    public static <#=wsName#>.SoCredentialsHeader AttachContactCredentialHeader() 
    { 
     <#=wsName#>.SoCredentialsHeader ch = new <#=wsName#>.SoCredentialsHeader(); 
     ch.AuthenticationType = <#=wsName#>.SoAuthenticationType.CRM5; 
     ch.UserId = "myUsername"; 
     ch.Secret = apUtilities.CalculateCredentialsSecret(<#=wsName#>.SoAuthenticationType.CRM5, 
       apUtilities.GetDays(), "myUsername", "myPassword"); 
     return ch; 
    } 
    }  
<# } #> 
} 

然後眼睜睜的看着一個whatever.cs神奇與期望出現代碼片段。這些被稱爲用於VS中代碼生成的T4模板。

你會想把它們變成部分類或擴展方法或其他東西。上面的代碼不會「按原樣」運行,但您明白了。

+0

我會給這個嘗試,我會搜索更多關於T4模板:) – balexandre 2009-01-04 18:59:59

0

我不知道這是不是你想考慮的事情,因爲它肯定有缺陷,但是 - 最終這些(varoius SoCredentialsHeader類)是不同命名空間中相同類定義的所有副本,所以一點點的重構你可以簡單地有一個類和一個方法。

將SoCredentialsHeader類定義複製到您自己的項目中,添加對其的引用並從所有Web服務的代理中刪除類定義。 在代理代碼文件的頂部添加使用語句,它不會說明區別。

基本上你已經告訴它爲所有Web服務使用相同的類定義(你的)。

顯而易見的一面是,無論何時更新和Web服務引用(並假定所有服務都使用相同的定義),都必須重複此練習,但我們一直在類似的場景中執行此操作爲我們工作得很好。

+0

這項工作是我想要避免的...你說什麼將是一樣的有一個枚舉和他們應用正確的命名空間:) – balexandre 2008-12-29 10:15:19

0

我會嘗試使用通用的方法,然後使用反射來設置屬性:

public static T AttachDiaryCredentialHeader<T>() where T: class 
{ 
    T ch = new T(); 
    Type objType = ch.GetType(); 
    PropertyInfo userId = objType.GetProperty("UserId"); 
    authType.SetValue(ch, "myUsername", null) 
    //And so on for the other properties... 
    return ch; 
} 

恕我直言,這有點哈克,我將讓他們分開,除非像以前的文章中提到,你」絕對確定這些服務的定義將保持不變。其中一個小的變化將打破這一點。

相關問題