我正在开发一个MVVM WPF应用程序,它使用服务器应用程序(WPF)托管的WCF服务。我有一些疑问,知道这是服务服务的最佳方式:
以下是简化的服务界面 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);
}
这样当我在 MainWindow 中实现 ISrvServiceCallback 接口以进行 PingReply 回调时,我还需要实现 GetUserControlAReply 和 GetUserControlBReply (现在我只是在没有代码的情况下实现它们)
MainWindow.xaml.cs中的GetUserControlAReply
public void GetUserControlAReply(string reply)
{
//nothing to do
}
当我在UserControlA的模型中实现 ISrvServiceCallback 接口时,会发生同样的事情:我必须实现 PingReply ,而不需要代码。
我不认为这是一种很好的合作方式。哪种解决此类问题的最佳做法?你能给我一些谈论这种情况的教程吗?
修改 正如@lokusking建议的那样,我提供了一个UserControl示例的Model和ViewModel。视图绑定到ViewModel的 LblStatus 。
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));
}
}
答案 0 :(得分:2)
创建一个单独的类来实现您的ISrvService
。
下一步使这个类成为Singleton。 现在,您可以在任何地方访问您的wcf函数,并且只有一个实现。
编辑:这是基于我之前代码的解决方案。
<强>实施强>
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);
}
}
<强>用法强>
SrvServiceCallbackProxy.Instance.PingReplyReceived += ..Here goes the method..
注意强>
我一直这样做。我将回调实现包装在Singleton-Proxy隧道服务器响应中,包含事件。
优点: 你有一个!始终可用的课程。 你只需要实现一次逻辑! 每个消费者都会收到您可以根据需要订阅的事件的通知。