В своем веб-приложении я использую несколько asmx (веб-служб) от одного и того же поставщика, у них есть один для этого, другой для этого, но для всех требуется заголовок SOAP с проверкой подлинности.
Добавить аутентификацию просто:
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 исходит (производный) от ОДНОГО веб-сервиса, и мне нужно добавить тот же код к другим, например:
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;
}
Есть ли способ реализовать шаблон проектирования, чтобы использовать только одну функцию, но которая подходит для всех веб-служб?
иногда вижу букву Т, это к чему? если да, как я могу реализовать такую функцию?
P.S. Я мог бы передать перечисление и использовать переключатель, чтобы проверить имя перечисления и применить правильный заголовок, но каждый раз, когда мне нужно добавить новый WebService, мне нужно добавить перечисление и код, я ищу для этого расширенный метод.
Спасибо.





Я не знаю, хотите ли вы это рассмотреть, поскольку у него определенно есть свои недостатки, но - поскольку в конечном итоге все они (классы varoius SoCredentialsHeader) являются копиями одного и того же определения класса в разных пространствах имен, поэтому с небольшим количеством при рефакторинге вы можете просто иметь один класс и один метод.
Скопируйте определение класса SoCredentialsHeader в собственный проект, добавьте ссылку на него и удалите определение класса из всех прокси-серверов веб-службы. Добавьте оператор using вверху файла кода прокси, и он не заметит разницы.
По сути, вы сказали ему использовать одно и то же определение класса (ваше) для всех веб-сервисов.
Очевидным недостатком является то, что вам нужно повторять это упражнение всякий раз, когда вы обновляете ссылку на веб-службу (и что предполагается, что все службы продолжают использовать одно и то же определение), но мы делали это в аналогичном сценарии, и это сработало довольно хорошо для нас.
Я бы попробовал использовать общий метод, а затем использовать отражение для установки свойств:
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;
}
ИМХО, это несколько хитроумно, я бы держал их отдельно, если только, как в предыдущем посте, не упоминалось об этом, вы абсолютно уверены, что определения этих сервисов останутся такими же. Одно небольшое изменение в одном из них сломает это.
Создайте файл с именем something.tt (трюк - расширение .tt) в любом месте вашего решения VS и вставьте следующий код:
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;
}
}
<# } #>
}
Затем посмотрите, как волшебным образом появляется файл something.cs с нужными фрагментами кода. Они называются шаблонами T4 для генерации кода в VS.
Вы захотите превратить их в частичные классы или методы расширения или что-то в этом роде. Приведенный выше код не будет работать «как есть», но вы поняли идею.
Я попробую и поищу больше о шаблонах T4 :)
эта работа - это то, чего я пытаюсь избежать ... то, что вы говорите, будет таким же, как наличие перечисления, и они применяют правильное пространство имен :)