簡體   English   中英

通用WCF代理實現

[英]Generic WCF proxy implementation

我正在編寫一個代理來訪問WCF服務,在這里我們可以訪問WCF服務和客戶端代碼。

對於服務合同界面中的每個方法,我正在編寫一個這樣的方法。

麻煩的是,界面中有很多方法,實際上這正在變成復制和粘貼練習。

有沒有更冗長的方法(使用lambdas?)而不是那么冗長? 我不能很快弄清楚。

public interface IServiceContract
{
   DataContracts.TypeA Method1(int arg1, string arg2);
   string Method2(string arg1);
   DateTime Method3();
   int Method4(DataContracts.Input1);
   // etc............
}


    public class Proxy : IServiceContract....

    public DataContracts.TypeA Method1(int arg1, string arg2)
    {
        IFileService proxy = null;
        ChannelFactory<IFileService> factory = null;
        try
        {
            factory = new ChannelFactory<IFileService>("*");
            proxy = factory.CreateChannel();
            return proxy.Method1(arg1, arg2);
        }
        finally
        {
            CloseConnection(proxy, factory);
        }
    }


     public List<AnOtherResultPoco> Method2(string arg1)
     {
         IFileService proxy = null;
         ChannelFactory<IFileService> factory = null;
         try
         {
             factory = new ChannelFactory<IFileService>("*");
             proxy = factory.CreateChannel();
             return proxy.Method2(args1);
         }
         finally
         {
             CloseConnection(proxy, factory);
         }
    }

    //ad inifinitum for methods,3,4,5...

如果您想使用lambda稍微分解一下代碼,建議您編寫一個如下所示的方法:

...
public void ServiceCall(Action<IFileService> action)
{
    IFileService proxy = null;
    ChannelFactory<IFileService> factory = null;
    try
    {
        factory = new ChannelFactory<IFileService>("*");
        proxy = factory.CreateChannel();
        return action(proxy);
    }
    finally
    {
        CloseConnection(proxy, factory);
    }
}

因此,您可以通過以下方式調用服務方法:

...
List<AnOtherResultPoco> result;
MyClass.ServiceCall(p => { result = p.Method2("hello"); });
...

您可以使用反射。

    public List<MyResultType> SearchBy(string searchTerm, string method)
    {
        IFileService proxy = null;
        ChannelFactory<IFileService> factory = null;
        try
        {
            factory = new ChannelFactory<IFileService>("*");
            proxy = factory.CreateChannel();
            if (!IsMethodAllowed(method))
            {
                throw new SecurityException();
            }
            return (List<MyResultType>)proxy.GetType().GetMethod(method).Invoke(proxy, new object[] { searchTerm });

        }
        finally
        {
            CloseConnection(proxy, factory);
        }
    }

這是另一種方式,也許您正在尋找什么。

    public List<MyResultType> SearchByMethod1(int a, int b)
    {
        return (List<MyResultType>)SearchBy(new object[] { a, b }, "Method1");
    }

    public List<MyResultType2> SearchByMethod2(MyResultType b)
    {
        return (List<MyResultType2>)SearchBy(new object[] { b }, "Method1");
    }

    protected object SearchBy(object[] parameters, string method)
    {
        IFileService proxy = null;
        ChannelFactory<IFileService> factory = null;
        try
        {
            factory = new ChannelFactory<IFileService>("*");
            proxy = factory.CreateChannel();
            if (!IsMethodAllowed(method))
            {
                throw new SecurityException();
            }
            return (List<MyResultType>)proxy.GetType().GetMethod(method).Invoke(proxy, parameters);

        }
        finally
        {
            CloseConnection(proxy, factory);
        }
    }

這不會導致泛型遍及您的代碼。 它被整齊地包裝在代理中。

我知道這是一個老問題,但是今天我遇到了同樣的問題,並且找到了一個簡單的解決方案,以為我可以與未來的用戶分享。 因此,在此解決方案中,我們將創建自己的代理,而不是生成服務引用。

這是代理,其目的是使其通用:

public class Proxy<T>
{
    public ChannelFactory<T> Channel { get; set; }

    public Proxy()
    {
        Channel = new ChannelFactory<T>("endpoint");
    }

    public T CreateChannel()
    {
        return Channel.CreateChannel();
    }
}

現在這是竅門:

對於無效方法:

public void Execute(Action<T> action)
{
    T proxy = CreateChannel();

    action(proxy);

    ((ICommunicationObject)proxy).Close();
}

退貨:

public TResult Execute<TResult>(Func<T, TResult> function)
    {
        T proxy = CreateChannel();

        var result = function(proxy);

        ((ICommunicationObject)proxy).Close();

        return result;
    }

其中TResult是返回類型。

如何使用:

Proxy<IService> proxy = new Proxy();
// for a void method
Proxy.Execute(prxy => prxy.Method());
// for non void method.
var result = Proxy.Execute(prxy => prxy.Method());

因此,總而言之,這是代理類的外觀:

public class Proxy<T>
    {
        public ChannelFactory<T> Channel { get; set; }

        public Proxy()
        {
            Channel = new ChannelFactory<T>("endpoint");
        }

        public T CreateChannel()
        {
            return Channel.CreateChannel();
        }

        public void Execute(Action<T> action)
        {
            T proxy = CreateChannel();

            action(proxy);

            ((ICommunicationObject)proxy).Close();
        }

        public TResult Execute<TResult>(Func<T, TResult> function)
        {
            T proxy = CreateChannel();

            var result = function(proxy);

            ((ICommunicationObject)proxy).Close();

            return result;
        }
    }

對於不使用任何服務引用的自定義wcf代理,我建議使用此解決方案,這確實非常簡單。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM