2

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.

matteo75
  • 31
  • 3

2 Answers2

2

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.

Dr. Wily's Apprentice
  • 10,212
  • 1
  • 25
  • 27
  • Thanks for your reply but my problem is not HOW to close a connection. I'd like to know how to inject a WCF/Web service as component and handle service connection properly. The problem is that having it as parameter in the constructor means that at class level I have just one instance of it and once is closed if another method is called an exception would be raised. It is also true that by default each service call is a different instance so this is probably just a philosophy problem.Hope it makes sense. – matteo75 Jan 16 '12 at 11:01
  • @matteo75 I guess it wasn't clear to me whether your approach"external component" is the channel factory or the channel. If the channel factory, then I'd be less concerned about disposal. I think that your approach is fine, but I would have your service implementation implement IDisposable and dispose of you external component. Set a breaking there just to verify that WCF honors it, which it should. – Dr. Wily's Apprentice Jan 16 '12 at 13:37
  • I'm using ChannelFactory but I havent implemented any service Disposal at the moment. I thought it'd be fine but I'm noticing on IIS an increasing use of memory (that is released after the recycle) which could be due to this unrelease services connections. Im not 100% sure, its just a guess, but it would be great to know a best practise for service Close/Dispose in a Dependency Injection architecture. – matteo75 Jan 16 '12 at 15:03
0

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.

Jeremy Rosenberg
  • 792
  • 6
  • 18