Вызов службы WCF с использованием метода расширения

#c# #wcf

#c# #wcf

Вопрос:

Я написал метод расширения для использования со службами WCF, который сохраняет всю логику удаления и обработки исключений в одном месте. Метод заключается в следующем:

 public static TResult CallMethod<TChannel, TResult>(
    this ClientBase<TChannel> proxy,
    Func<TResult> func) where TChannel : class
{
    proxy.ThrowIfNull("proxy");
    func.ThrowIfNull("func");

    try
    {
        // set client credentials
        return func();
    }
    finally
    {
        if (proxy != null)
        {
            try
            {
                if (proxy.State != CommunicationState.Faulted)
                {
                    proxy.Close();
                }
                else
                {
                    proxy.Abort();
                }
            }
            catch (CommunicationException)
            {
                proxy.Abort();
            }
            catch (TimeoutException)
            {
                proxy.Abort();
            }
            catch (Exception)
            {
                proxy.Abort();
                throw;
            }
        }
    }
}
  

Метод будет использоваться следующим образом:

 public int CreateBusinessObject(BusinessObject item)
{
    MyServiceClient proxy = new MyServiceClient();
    return proxy.CallMethod(() => proxy.CreateBusinessObject(item));
}
  

Мой вопрос на самом деле заключается в том, было бы ли это лучше в качестве статического метода, который создает прокси-сервер службы? Я немного беспокоюсь о своей текущей реализации. Должна ли конструкция прокси-сервера находиться внутри try / catch? Мое текущее понимание заключается в том, что если конструктор выходит из строя, в любом случае утилизировать нечего.

Ответ №1:

Если конструктор выходит из строя, весь объект находится в недопустимом состоянии. Вам не следует беспокоиться об утилизации в этом случае.

Хорошим тестом для этого является то, что произойдет, когда вы выполните следующее:

 class Program
{
    static void Main(string[] args)
    {
        using (new TestClass())
        {
            Console.WriteLine("In using");
        }
    }

    class TestClass : IDisposable
    {
        public TestClass()
        {
            throw new Exception();
        }

        public void Dispose()
        {
            Console.WriteLine("Disposed");
        }
    }
}
  

Результатом является то, что удаление никогда не достигается. Это то, что происходит при сбое конструктора.

Комментарии:

1. Хороший момент. Я должен был догадаться попробовать что-то подобное. Спасибо.