通用WCF代理实现



我正在编写一个访问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代理,而不使用任何服务引用,它非常简单。

最新更新