matteo75
matteo75

Reputation: 31

WCF and dependency injection

I have a set of WCF services implemented using dependency injection for testing purposes.

Basically these services sometimes call each other, so on my Unit Tests I could mock both repositories and WCF services just using interfaces and injecting them as components in the service constructors.

This is great as I can test these services properly without any dependency.

I have also implemented my own proxies in order to avoid using Visual Studio service reference (which creates a lot of rubbish), so I'm using ChannelFactory CreateChannel method.

I'm a bit worried about what happens on the live enviroment.

What happens is that my WCF service that calls another WCF service has only one instance of this external component injected in the constructor and because of this I cannot dispose this object once used.

Is this going to create troubles? Will garbage collector take care of it? Will connections remain open? Is this approach wrong?

Thanks a lot.

Upvotes: 2

Views: 1098

Answers (2)

Jeremy Rosenberg
Jeremy Rosenberg

Reputation: 792

Yes, you should close your channels that you open. You haven't specified who actually uses the channel factory to open the channel. Whoever receives an open channel from calling the factory is responsible for closing it, since that is the only place that has the knowledge of when it is permissible to do so.

Generally, you should open your channel, make a call, and immediately close it to release the connection to the pool. ChannelFactory<T> is optimized for this and will reuse available connections when practical and only have the contracts processed, etc., once.

Given these points, my favorite so far is having another abstraction to explicitly define these open-invoke-close semantics. I call that IChannelInvoker<T> which has a single Execute method. The version I have right now is async only, but for simplicity here, here's what a synchronous version would look like:

public interface IChannelInvoker<TChannel>
{
    /// <summary>
    /// Executes a method within the context of an open channel
    /// </summary>
    TResult Execute<TResult>(Func<TChannel, TResult> method);
}

An implementation's Execute method uses a ChannelFactory to open the channel, invokes the delegate, closes the channel, and returns the result. I have the factory injected there and kept around for the lifetime of the app.

Now in service A, instead of injecting the channel T, you inject an IChannelInvoker<T>. For example:

public class ServiceA : IServiceA
{
    private readonly IChannelInvoker<IServiceB> _b;

    public ServiceA(IChannelInvoker<IServiceB> b)
    {
        _b = b;
    }

    public void SomeOperationA()
    {
        _b.Execute(channel => channel.SomeOperationB());
    }
}

The invoker is also composable, so you can add other IChannelInvoker<T> decorators to apply cross cutting concerns like security at the message level - adding headers, etc.

Upvotes: 0

Dr. Wily&#39;s Apprentice
Dr. Wily&#39;s Apprentice

Reputation: 10280

A ChannelFactory creates a channel object when you call the CreateChannel method. This channel object is what actually has the connection.

Once you're done with the channel, you should close it by calling the IClientChannel.Close method on it. That should cause any underlying network connection to be closed. Note that in some situations calling the Close method can cause a CommunicationObjectFaultedException exception, even if you verify first that your channel is not in a Faulted state.

You can see in the code example of this MSDN documentation page that the Close method is called on the wcfClientChannel object.

Upvotes: 2

Related Questions