Reputation: 1491
I am writing a proxy to access a WCF service where we have access to both the WCF service and the client's code.
For each method in the Service contract interface I am writing a method like this.
The trouble is that there are many methods in the interface and effectively this is turning into a copy and paste exercise.
Is there a more elegant way (with lambdas?) of doing this that isn't so verbose ? I can't quick figure it out please....
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...
Upvotes: 1
Views: 3445
Reputation: 4245
I know its an old question, but I run into the same problem today, and found an easy solution, thought I would share for future users. So in this solution, we will make our own proxy instead of generating a service reference.
Here is the Proxy, The idea is to make it generic:
public class Proxy<T>
{
public ChannelFactory<T> Channel { get; set; }
public Proxy()
{
Channel = new ChannelFactory<T>("endpoint");
}
public T CreateChannel()
{
return Channel.CreateChannel();
}
}
Now here is the trick :
For void methods :
public void Execute(Action<T> action)
{
T proxy = CreateChannel();
action(proxy);
((ICommunicationObject)proxy).Close();
}
For return:
public TResult Execute<TResult>(Func<T, TResult> function)
{
T proxy = CreateChannel();
var result = function(proxy);
((ICommunicationObject)proxy).Close();
return result;
}
Where the TResult is the returning type.
How to use:
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());
So, to sum up, here is how the proxy class should look like:
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;
}
}
I recommend this solution for a custom wcf proxy without using any service reference, its really simple and easy.
Upvotes: 0
Reputation: 18031
If you want to factorize your code a bit using lambda, I suggest to write a method that looks like this:
...
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);
}
}
So you call your service methods this way:
...
List<AnOtherResultPoco> result;
MyClass.ServiceCall(p => { result = p.Method2("hello"); });
...
Upvotes: 3
Reputation: 66
You could use reflection.
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);
}
}
This is another way, maybe what you are looking for.
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);
}
}
This would not lead to having generics all over your code. It is neatly wrapped inside proxy.
Upvotes: 1