Как я могу сделать несколько вызовов веб-службы SOAP универсальными, чтобы уменьшить избыточность? - PullRequest
0 голосов
/ 25 сентября 2019

У меня есть эти методы ниже, которые вызывают некоторые веб-сервисы SOAP, все от одного и того же провайдера, поэтому у них у всех одинаковые методы / вызовы / и т. Д.Я ищу более ООП / абстрактный способ вызвать их, не написав так много методов?В идеале я хотел бы, чтобы для каждого был один метод -> GetClaim (), AddClaim (), SearchClaim (), RemoveClaim () и т. Д.

Вопрос - Должен ли я передать параметры, специфичные для службы, чтобы сделатьметод более универсальный, исключив 15 других методов, подобных этому, или есть более подход более рациональный / абстрактный?Может кто-нибудь, пожалуйста, предоставьте мне пример?

    // ex. how can I make these two methods 1?
    public async void ClaimSearchForWRG(string url, string userName, string password) {
        var client = new WebServiceWRGClient(); 
        var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
        var endpoint = new EndpointAddress(url); 
        var channelFactory = new ChannelFactory<WebServiceWRG>(binding, endpoint); 
        var webService = channelFactory.CreateChannel();
        var user = new User(); 
        user.UserName = await webService.EncryptValueAsync(userName);
        user.Password = await webService.EncryptValueAsync(password);
        var response = await client.ClaimSearchAsync(user, "", "", 12345, statuscode.NotSet, "");
    }

    // another call (same provider) with the same call ->  ClaimSearchAsync()
    public async void ClaimSearchForAWI(string url, string userName, string password) {
        var client = new WebServiceAWIClient(); 
        var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
        var endpoint = new EndpointAddress(url); 
        var channelFactory = new ChannelFactory<WebServiceAWI>(binding, endpoint); 
        var webService = channelFactory.CreateChannel();
        var user = new ArmUser(); 
        user.UserName = await webService.EncryptValueAsync(userName);
        user.Password = await webService.EncryptValueAsync(password);
        var response = await client.ClaimSearchAsync(user, "", "", 12345, ArmStatuscode.NotSet, "");
    }
    // then we have 15 other web service calls from the same provider for ClaimSearchAsync()
    // then we have 15 more calls for ClaimGetAsync()
    // then we have 15 more calls for AddClaimAsync()
    // then we have 15 more calls for RemoveClaimAsync()
    // etc, etc, etc

ОБНОВЛЕНО После попытки этого кода ниже, чтобы сделать вещи немного более универсальными (чтобы устранить избыточность), я получаю некоторые ошибки вкод.Специально связано с тем, что компилятор не находит свойства, связанные с общими сущностями, которые я передаю в метод.ех.user.Username не найден -> в сообщении об ошибке говорится, что «TTwo» не содержит определения «UserName»

    public class Test {
        public void TestWebService() {
            var ws = new WebService<WebServiceWRG>();
            ws.SearchClaim(new WebServiceWRGClient(), new GraceUser(), 
                "https://trustonline.delawarecpf.com/tows/webservicewrg.svc", "userName", "password");  
        }
    }

    public class WebService<T> {             
        public void SearchClaim<TOne, TTwo>(TOne entity1, TTwo entity2, string url, string userName, string password) 
            where TOne : class
            where TTwo : class
        {
            var client = entity1;
            var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
            var endpoint = new EndpointAddress(url);
            var channelFactory = new ChannelFactory<T>(binding, endpoint);
            var webService = channelFactory.CreateChannel();
            var user = entity2;
            user.UserName = webService.EncryptValue(userName);
            user.Password = webService.EncryptValue(password);
            var response = client.ClaimSearch(user, "", "", 12345, GraceStatuscode.NotSet, "");
        }
    }

1 Ответ

0 голосов
/ 25 сентября 2019

Не уверен, какова ваша структура кода, но я просто сосредоточусь на предоставленном примере.

Из того, что я видел, если этот метод и другие связанные методы используются в разных классах, я бы предложил создать класс, который будет обрабатывать его, а затем использовать этот класс вместо методов.Но если этот метод и другие связанные методы используются в определенном классе, я бы порекомендовал создать универсальные методы, которые заменят избыточные методы.Сначала вам нужно будет сравнить все связанные методы и получить между ними общий числитель, чтобы сделать это отправной точкой для общего подхода.

Вот непроверенный пример (на основе того, что я понял из вашего примера):

public class CallWebService<T> // don't forget to inherit IDisposal.
{

    private WebServiceWRGClient Client {get; set;}

    private BasicHttpBinding HttpBinding {get; set;}

    private EndpointAddress  Endpoint {get; set;}

    private ChannelFactory Channel {get; set;}

    // if needed outside this class, make it public to be accessed globally. 
    private User UserAccount {get; set;}

    public CallWebService<T>(string url)
    {
        Client      = new WebServiceWRGClient(); 

        //See which Binding is the default and use it in this constructor. 
        HttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);

        Endpoint    = new EndpointAddress(url); 

        // T is generic, WebServiceWRG in this example 
        Channel     = new ChannelFactory<T>(HttpBinding, Endpoint).CreateChannel();

        UserAccount = new User();
    }

    // another constructor with BasicHttpBinding
    public CallWebService<T>(string url, BasicHttpSecurityMode securityMode)
    {
        Client      = new WebServiceWRGClient(); 

        //See which Binding is the default and use it in this constructor. 
        HttpBinding = new BasicHttpBinding(securityMode);

        Endpoint    = new EndpointAddress(url); 

        // T is generic, WebServiceWRG in this example 
        Channel     = new ChannelFactory<T>(HttpBinding, Endpoint).CreateChannel();

        UserAccount = new User();

    }

    // Change this method to return the response. Task<Response> is just a placeholder for this example 
    public async Task<Response> Call(string userName, string password)
    {
        UserAccount.UserName = await Channel.EncryptValueAsync(userName);

        UserAccount.Password = await Channel.EncryptValueAsync(password);

        var response = await Client.ClaimSearchAsync(User, "", "", 12345, statuscode.NotSet, "");       
    }

    /*
        [To-Do] : gather all other releated methods into this class, then try to simplify them. 

    */

}

Вы также можете настроить конструкторы по мере необходимости, например, вы можете создавать конструкторы, которые принимают WebServiceWRGClient и BasicHttpBinding .. и т. д.Итак, он более открыт для вас.

Вы можете сделать аналогичный подход, если он будет использоваться во всем проекте, но если он используется только в одном классе, то вы можете сделать что-то вроде этого:

// Configure it as needed, but avoid using `void` with async, as the exceptions in sync and async methods handled differently. 
// Also, try to make sense here, make the method return the results.
public async Task CallWebService<T>(WebServiceWRGClient client,  string url, string userName, string password) 
{

    var channelFactory = new ChannelFactory<T>(new BasicHttpBinding(BasicHttpSecurityMode.Transport, new EndpointAddress(url)).CreateChannel(); 
    var user = new User(); // coming from service reference

    user.UserName = await channelFactory.EncryptValueAsync(userName);
    user.Password = await channelFactory.EncryptValueAsync(password);
    var response  = await client.ClaimSearchAsync(user, "", "", 12345, statuscode.NotSet, "");
}
...