Question

Adding a service reference to a web service (this is all WCF) in Visual Studio produces some generated code including a client-side restatement of the interface being exposed.

I understand why this interface is generated: you might be consuming a 3rd party service and not have access to the actual interface.

But I do, and the two are not assignment compatible even though the transparent proxy does indeed exactly implement the interface to which I want to cast.

I can use reflection, but that's ugly. Is there some way to defeat this faux type safety and inject metadata to so I can use an interface with a class?


My specific problem departs from the norm in complicated ways that have to do with a single client that uses some derivatives of a base class directly and uses others remotely via service references. The base class for each server needs to keep references to subscribing clients in a collection for enumeration to notify events, and the problem was type varied due to the use of proxies.

None of these answers solves my specific problem, yet every single answer was instructive and helpful. I found my own solution (use a dual binding) but I would never have figured it out if you hadn't radically improved my understanding of the whole business.

Three excellent answers. How to choose just one? I choose the first, because it directly solves the problem I first thought I had.

Was it helpful?

Solution

When you add the service reference, go to "Advanced" and make sure "Reuse types in referenced assemblies" is selected and that the assembly containing your interface definition is selected. You can also do this with an existing service reference by right clicking on it and going to "Configure".

OTHER TIPS

If you already have the contract dll at the client, you don't even need a service reference (unless you are using it to write the setup code for you) - you can simply subclass ClientBase and expose the Channel, and use that directly - something like (no IDE handy...):

public class WcfClient<T> : ClientBase<T> where T : class
{
    public new T Channel {get {return base.Channel;}}
}

Then you can just do things like:

using(var client = new WcfClient<IFoo>())
{
    client.Channel.Bar(); // defined by IFoo
}

You still need the configuration settings in the config to determine the address, binding, etc - but less messy than proxy generation. Also, you might choose to re-implement IDipsoable to deal with the fact that WCF proxies can throw in Dispose() (which is bad):

public class WcfClient<T> : ClientBase<T>, IDisposable where T : class
{
    public new T Channel {get {return base.Channel;}}
    void IDisposable.Dispose() {
        try {
           switch(State) {
              case CommunicationState.Open: Close(); break;
              // etc
           }
        } catch {} // swallow it down (perhaps log it first)
    }
}

In order to return an interface from a service you need to use the KnownType attribute:

Does any of that help?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top