wcf duplex service lose coupling with client

472 Views Asked by At

I have been stuck on an issue for 2 weeks.

Let's assume we have a Duplex WCF Service and a Client application that calls the service.

The app has a class MyCallBackClass that is composed of the service. What I would like to achieve is to pass the instantiated service in the constructor of the MyCallBackClass client app (lose coupling). So it would look something like service with one method and callback with one method:

DUPLEX SERVICE CONTRACT:

[ServiceContract(SessionMode=SessionMode.Required,CallbackContract=typeof(ICallback))]
public interface IService{

 [OperationContract(IsOneWay = true)]
 void GetDataFromService();

}

DUPLEX CALLBACK:

public interface ICallback{

[OperationContract(IsOneWay = true)]
void ReceiveMessage(string message);

}

DUPLEX SERVICE Implementation

public class Service : IService{

//... here a reference to the Callback endpoint

void GetDataFromService(){

callBackEndPoint.ReceiveMessage("Service was called.");
}
}

MY CLASS THAT IMPLEMENTS CALLBACK:

public class MyCallBackClass : ICallback, Widnows.Form
{
IService service;

public MyCallBackClass (){

InstanceContext instanceContext = new InstanceContext(this);

this.service = new ServiceClient(instanceContext);

}

public ReceiveMessage(string message){

this.textBoxMessage.Text = message;
//here I want to stress that I would like my CallBack object to be a Form or WPF Form
//so that I can react on callbacks by modyfing the Controls like TextBox, ListBox directly

}

}

Now in the application I am forced to instantiate the service in the constructor of the object that implements callback interface, lets assume it is a Form, or WPF Form (as follows):

public void Main(string[] args){

MyCallBackClass myWindow = new MyCallBackClass();

myWindow.GetDataFromService();

}

What I would like to have is to PASS THE SERVICE in Constructor of the callback handler, as follows:

public void Main(string[] args){

Iservice service = new ServiceClient();// but what about the InstanceContext that is the MyCallBackClass object...???

MyCallBackClass myWindow = new MyCallBackClass(service);

myWindow.GetDataFromService();

}

And ofcourse the class's MyCallBackClass constructor would change to this:

public class MyCallBackClass : ICallback, Widnows.Form
{
IService service;

public MyCallBackClass (IService _service){

InstanceContext instanceContext = new InstanceContext(this);

this.service = _service;

...
}

So that I can inject any type of service that implements IService interface to the client class and it is easy to test the client class by mocking the Service. Unfortunately I come across a DEPENDENCY LOOP. The InstanceContext dependson MyCallBackClass that dependson IService that dependson InstanceContext...

Could you please try to understand and try to guide me to any direction that would solve this issue?

1

There are 1 best solutions below

1
On

You could try this. win.service.Value is time when Service is first time used that it will be instanciated (referenced original with delegate). This could be done as well with method SetService on Windows, the difference is that someone might forget to call it when Windows instance is created. All mandatory items must be in the constructor of Windows, that is Contract, Function as well as Lazy load makes your Dependency live :)

You should definitely refactor your code, try to read about SOLID principles.

public class Service
{
    private int number;
    private Window win;

    public Service(int num, Window win)
    {
        number = num;
        this.win = win;
    }
}

public class Window
{
    public Lazy<Service> service;

    public Window(Func<Service> getService)
    {
        service = new Lazy<Service>(getService);
    }
}


    static void Main(string[] args)
    {
        Service  s = null;

        var win = new Window(() => s);

        s = new Service(1, win);

        Service winS = win.service.Value;
    }