views:

924

answers:

2

I am trying to consume a wcf rest service via reflection if possible. Take a look at the code below:

    public static object WCFRestClient<T>(string method, string uri, params object[] args)
    {        
        object o;
        object ret;
        using (ChannelFactory<T> cf = new ChannelFactory<T>(new WebHttpBinding(), uri))
        {                
            T contract = cf.CreateChannel();
            ret = contract.GetType().GetMethod(method).Invoke(o, args);

        }
        return ret;
    }

As you see it is a generic method that takes T at run time... my trouble is, I am not sure if I can really reflect on the channel object I am creating above.... Lets say I do, then the trouble starts when I want to create an object instance... Since I can't create an object instance from an interface...

I would also be happy to hear about if there is any other way to accomplish this? But I prefer to use channel mechanism if I can.

+2  A: 

In general, creating a ChannelFactory for every operation is expensive. You should avoid that if possible. The using pattern is also problematic for ICommunicationObject types in WCF, since Dispose() generally corresponds to Close() which is a blocking/exception-throwing call. You will want to call Close() explicitly instead and handle TimeoutException and CommunicationException.

Aside from that, your approach would work. If you use ChannelFactory<T>.CreateChannel, it will create a transparent proxy object of type T which could be called upon via reflection if you want. So you won't have to worry about creating an object from the contract interface -- WCF already does that.

In your code sample, make sure to replace the o with contract and you should get the results you expect.

bobbymcr
Ive tried your approach but now I am getting the errorSystem.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: Manual addressing is enabled on this factory, so all messages sent must be pre-addressed..
theKing
I think you need to add the WebHttpBehavior to your factory: factory.Endpoint.Behaviors.Add(new WebHttpBehavior());
bobbymcr
Yess!!, thank works. thanks a bunch
theKing
A: 

Ignoring what you're trying to do for a second, just look at the unnecessary things you're doing in that method. The method below does exactly the same thing as yours.

public static object WCFRestClient<T>(string method, string uri, params object[] args) {
    using (ChannelFactory<T> cf = new ChannelFactory<T>(new WebHttpBinding(), uri)) 
        return cf.CreateChannel().GetType().GetMethod(method).Invoke(null, args);
}

You turned a 4 line function into an 11 line function and actually reduced the readability of the code introducing unnecessary variables that force the reader to stop and wonder why you did that.

Ramon
First of all, the question is not about readability... So you are off the topic to start with. And if you think your snippet is more readable than what I have provided, good luck to you in your career.
theKing
I find the original poster's code more readable. Excessive terseness is generally *less* readable, in my experience.
bobbymcr
StackOverflow questions are not a place to critique other people's coding style. Therefore, I will refrain from commenting on your code.
Darrel Miller