2008-12-29 104 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; 
} 

恕我直言,这有点哈克,我将让他们分开,除非像以前的文章中提到,你”绝对确定这些服务的定义将保持不变。其中一个小的变化将打破这一点。

相关问题