tags:

views:

420

answers:

3

Hi,

please help me solve this issue.

I have a client using WCF. I don't want this client to know that it gets its data from a service. I want to use a model like this so I it easier for me to unit test the code and to later replace the implementation of the given interface. The problem with this model is that I'm not able to call close on the ChannelFactory. I'm not sure that I need to call close, but it feels right.

So my question is:

Does anybody know of a good pattern for closing the ChannelFactory when the client only should know the interface of the service? Or is the ChannelFactory closed by it self by some kind of magic?

Below is some sample code that I hope will you understand the question:

    static void Main(string[] args)
    {
        ITestService service = GetTestService();
        Console.WriteLine(service.GetData(42));

    }

    private static ITestService GetTestService()
    {
        var cf = new ChannelFactory<ITestService>(new WSHttpBinding(), new EndpointAddress("http://localhost:8731/TestService/"));
        return cf.CreateChannel();
    }

Thanks, GAT

+2  A: 

The best way to solve this is to keep the reference to the ChannelFactory alive for as long as you need it. So take the creation of the ChannelFactory out of the GetTestService method and create the factory on initialization of your class (in the constructor for example) and close it when you no longer need the factory (in the Dispose method of your class for example).

ChannelFactory is a factory class that you can reuse as many times as you like, so there is no need to create it each time you need a service implementation.

Ronald Wildenberg
This sounds like a nice solution. So what I can do is to have my own "ServiceFactory" that contains a static ChannelFactory<ITestService>. Every time I need a channel I will call CreateChannel() on this member. And when the application is terminated I call close on the ChannelFactory.Does that sound like the correct way to do this?
GAT
That's the correct way. The main point is that you should not create a new ChannelFactory every time you need a channel. There is no problem in keeping a ChannelFactory alive for the duration of the program.
Ronald Wildenberg
+2  A: 

Hello,

You should implement class like

public class MyClient : ITestService 
{
private ChannelFactory<ITestService> factory;
private ITestService proxy;
//...
//expose here methods Open and Close that internally will open and close channel factory
//implement interface members
}

The lifetime of the client here will be the same as lifetime of channel factory.

Vitaliy Liptchinsky
This also sounds like a nice solution. So what you want me to do is to make a wrapper for my service that I can use in my application?
GAT
I accepted the answer from @rwwilden since he answered first. I think both answers where very good, so I voted up your answere.
GAT
+1  A: 

Have you tried casting it to a IClientChannel and then calling Close?

((IClientChannel)service).Close();
RichardOD
I guess that would work. But I don't want my client to know of IClientChannel. This would destroy my unit test since my FakeService is not implementing IClientChannel.
GAT
Yeap- personally I'd go with rwwilden's solution. I was going to add that but my Internet connection dropped on the train!
RichardOD
I guess you use the C# as operator instead and only call Close if it is not null. That would allow your unit tests to not fail- see here: http://msdn.microsoft.com/en-us/library/cscsdfbt.aspx
RichardOD