Reputation: 135
I'm developing a MVVM WPF application that consumes a WCF service hosted by a server application (WPF). I have some doubts about which is the best way to consume the service knowing that:
Here is the simplified service interface ISrvService.cs
[ServiceContract(CallbackContract = typeof(ISrvServiceCallback))]
public interface ISrvService
{
[OperationContract(IsOneWay = true)]
void Ping();
[OperationContract(IsOneWay = true)]
void GetUserControlAStatus();
[OperationContract(IsOneWay = true)]
void GetUserControlBStatus();
}
public interface ISrvServiceCallback
{
[OperationContract(IsOneWay = true)]
void PingReply(string reply);
[OperationContract(IsOneWay = true)]
void GetUserControlAReply(string reply);
[OperationContract(IsOneWay = true)]
void GetUserControlAReply(string reply);
}
In this way when I implement ISrvServiceCallback interface in MainWindow to have PingReply callback, I also need to implement GetUserControlAReply and GetUserControlBReply (right now I just implement them with no code)
GetUserControlAReply in MainWindow.xaml.cs
public void GetUserControlAReply(string reply)
{
//nothing to do
}
The same thing happens when I implement the ISrvServiceCallback interface in the model of the UserControlA: i have to implement PingReply with no code inside.
I don't think this is a good way to work with. Which are the best practices to solve this kind of problem? Can you suggest me some tutorials that talk about this situation?
EDIT As @lokusking suggested, I provide Model and ViewModel of a example of UserControl. The View is binded to LblStatus of ViewModel.
UserControlAModel.cs
public class UserControlAModel: INotifyPropertyChanged, SrvService.ISrvServiceCallback
{
System.ServiceModel.InstanceContext instanceContext;
SrvService.SrvServiceClient client;
public event PropertyChangedEventHandler PropertyChanged;
private string _Status;
public string Status
{
get { return _Status; }
set { _Status = value; NotifyPropertyChanged(); }
}
public UserControlAModel()
{
Status = "NOT CONNECTED";
}
public void GetStatus()
{
instanceContext = new System.ServiceModel.InstanceContext(this);
client = new SrvService.SrvServiceClient(instanceContext);
client.GetUserControlAStatus();
}
private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
//callbacks implementation
public void GetUserControlAReply(string reply)
{
Status = reply;
}
public void GetUserControlBReply(string reply)
{
//nothing to do
}
public void PingReply(string reply)
{
//nothing to do
}
}
UserControlAViewModel.cs
public class UserControlAViewModel : INotifyPropertyChanged
{
private UserControlAModel _uControlAModel;
public UserControlAModel MyUserControlAModel
{
get
{ return _uControlAModel; }
set
{ _uControlAModel = value; NotifyPropertyChanged(); }
}
public string LblStatus
{
get { return MyUserControlAModel.Status; }
set { MyUserControlAModel.Status = value; NotifyPropertyChanged(); }
}
public UserControlAViewModel()
{
MyUserControlAModel = new UserControlAModel();
MyUserControlAModel.PropertyChanged -= UserControlAModel_PropertyChanged;
MyUserControlAModel.PropertyChanged += UserControlAModel_PropertyChanged;
MyUserControlAModel.GetStatus();
}
private void UserControlAModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
NotifyPropertyChanged(string.Empty);
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Upvotes: 3
Views: 531
Reputation: 7456
Make a seperate class which implents your ISrvService
.
Next step make this class a Singleton. Now you can access your wcf-functions everywhere and have only one Implementation.
EDIT: This is a solution based on my previous code.
Implementation
public class SrvServiceCallbackProxy : ISrvServiceCallback
{
public event EventHandler PingReplyReceived;
private SrvServiceClient _innerClient;
private SrvServiceCallbackProxy() {
var instanceContext = new System.ServiceModel.InstanceContext(this);
_innerClient = new SrvService.SrvServiceClient(instanceContext);
}
private static SrvServiceCallbackProxy _instance;
public static SrvServiceCallbackProxy Instance => _instance ?? (_instance = new SrvServiceCallbackProxy());
public void PingReply(string reply) {
this.PingReplyReceived?.Invoke(reply, EventArgs.Empty);
}
}
Usage
SrvServiceCallbackProxy.Instance.PingReplyReceived += ..Here goes the method..
NOTE
Im doing this all the time. Im wrapping my callback-implementation in Singleton-Proxy tunneling server-responses with events.
Benefits: You have ONE! class which is always available. You have only to implement your Logic once! Every consumer will get notified by events you can subsrcribe to on demand.
Upvotes: 3