Create an all-in-one function using DS in C #

In my web application I am using multiple asmx (web services) from the same provider, they have one for this, another for this, but all require a SOAP header with authentication.

Just add authentication:

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;
}

      

The problem is that this SoCredentialsHeader comes (derivation) from ONE webservice and I need to add the same code to others, for example:

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;
}

      

Is there a way to implement a design pattern to only use one function, but that works across all web services?

Sometimes I see the letter T , is that for that? if so how can i accomplish such a function?

PS I can pass an enum and use a switch to check the enum name and apply the correct header, but every time I need to add a new WebService I need to add an enum and code, I was looking for an advanced technique for that.

Thank.

0


source to share


3 answers


Create a file called whatever.tt (trick is .tt extension) anywhere in your VS solution and paste the following code:

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;
    }
    }       
<# } #>
}

      



Then watch any.cs magically appear with the desired code snippets. They are called T4 templates for code generation in VS.

You will want to turn them into partial classes or extension methods or whatever. The above code won't function "as is", but you get the idea.

+3


source


I don't know if this is what you want to consider as it definitely has it on the sides, but since ultimately these classes (varoius SoCredentialsHeader classes) are copies of the same class definition in different namespaces, so with a little refactoring you could just have one class and one method.

Copy the definition of the SoCredentialsHeader class into your own project, add a reference to it, and remove the class definition from all Web service proxies. Add a using statement at the top of the proxy code file and it wouldn't tell a difference.



Basically you told him to use the same class definition (yours) for all web services.

The obvious side is that you need to repeat this exercise whenever you update and reference a web service (and assume that all services continue to use the same definition), but we did it in a similar scenario and this worked pretty well for us.

0


source


I would try the generic method and then use reflection to set properties:

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;
}

      

IMHO this is somewhat hacky, I would keep them separate if, as mentioned in the previous post, you are absolutely sure that the definitions of these services will remain the same. One minor change to one of them will break this.

0


source







All Articles