Wcf 将Silverlight客户端与服务引用生成的类解耦
我正在通过快速入门来研究Prism v2。我已经创建了具有以下签名的WCF服务:Wcf 将Silverlight客户端与服务引用生成的类解耦,wcf,silverlight,prism,Wcf,Silverlight,Prism,我正在通过快速入门来研究Prism v2。我已经创建了具有以下签名的WCF服务: namespace HelloWorld.Silverlight.Web { [ServiceContract(Namespace = "http://helloworld.org/messaging")] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityR
namespace HelloWorld.Silverlight.Web
{
[ServiceContract(Namespace = "http://helloworld.org/messaging")]
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
public class HelloWorldMessageService
{
private string message = "Hello from WCF";
[OperationContract]
public void UpdateMessage(string message)
{
this.message = message;
}
[OperationContract]
public string GetMessage()
{
return message;
}
}
}
当我在silverlight项目中添加对此服务的服务引用时,它会生成一个接口和一个类:
[System.ServiceModel.ServiceContractAttribute
(Namespace="http://helloworld.org/messaging",
ConfigurationName="Web.Services.HelloWorldMessageService")]
public interface HelloWorldMessageService {
[System.ServiceModel.OperationContractAttribute
(AsyncPattern=true,
Action="http://helloworld.org/messaging/HelloWorldMessageService/UpdateMessage",
ReplyAction="http://helloworld.org/messaging/HelloWorldMessageService/UpdateMessageResponse")]
System.IAsyncResult BeginUpdateMessage(string message, System.AsyncCallback callback, object asyncState);
void EndUpdateMessage(System.IAsyncResult result);
[System.ServiceModel.OperationContractAttribute(AsyncPattern=true, Action="http://helloworld.org/messaging/HelloWorldMessageService/GetMessage", ReplyAction="http://helloworld.org/messaging/HelloWorldMessageService/GetMessageResponse")]
System.IAsyncResult BeginGetMessage(System.AsyncCallback callback, object asyncState);
string EndGetMessage(System.IAsyncResult result);
}
public partial class HelloWorldMessageServiceClient : System.ServiceModel.ClientBase<HelloWorld.Core.Web.Services.HelloWorldMessageService>, HelloWorld.Core.Web.Services.HelloWorldMessageService {
{
// implementation
}
异常是由
应用程序引发的。Current.RootVisual
传递接口(一旦实例化了客户端)应该与使用HelloWorldMessageService而不是HelloWorldMessageServiceClient类一样简单
为了更新UI,您需要使用Dispatcher对象。这允许您提供在UI线程上下文中调用的委托。有关详细信息,请参见此部分。好的,所以我真正的问题是如何将我对服务引用创建的代理类的依赖性解耦。我试图通过使用与代理类一起生成的接口来实现这一点。这本可以很好地工作,但我还必须引用拥有服务引用的项目,因此它不会真正解耦。这就是我最后要做的。这是一个有点黑客,但它似乎是工作,到目前为止 首先,这里是我的接口定义和使用我的代理生成的自定义事件处理程序args的适配器类:
using System.ComponentModel;
namespace HelloWorld.Interfaces.Services
{
public class GetMessageCompletedEventArgsAdapter : System.ComponentModel.AsyncCompletedEventArgs
{
private object[] results;
public GetMessageCompletedEventArgsAdapter(object[] results, System.Exception exception, bool cancelled, object userState) :
base(exception, cancelled, userState)
{
this.results = results;
}
public string Result
{
get
{
base.RaiseExceptionIfNecessary();
return ((string)(this.results[0]));
}
}
}
/// <summary>
/// Create a partial class file for the service reference (reference.cs) that assigns
/// this interface to the class - then you can use this reference instead of the
/// one that isn't working
/// </summary>
public interface IMessageServiceClient
{
event System.EventHandler<GetMessageCompletedEventArgsAdapter> GetMessageCompleted;
event System.EventHandler<AsyncCompletedEventArgs> UpdateMessageCompleted;
void GetMessageAsync();
void GetMessageAsync(object userState);
void UpdateMessageAsync(string message);
void UpdateMessageAsync(string message, object userState);
}
}
使用System.ComponentModel;
命名空间HelloWorld.Interfaces.Services
{
公共类GetMessageCompletedEventArgs适配器:System.ComponentModel.AsyncCompletedEventArgs
{
私有对象[]结果;
public GetMessageCompletedEventArgsAdapter(对象[]结果,系统异常,bool已取消,对象用户状态):
基本(异常、已取消、用户状态)
{
这个结果=结果;
}
公共字符串结果
{
得到
{
base.RaiseExceptionIfEssential();
返回((字符串)(this.results[0]);
}
}
}
///
///为分配的服务引用(reference.cs)创建分部类文件
///将此接口添加到类-然后可以使用此引用而不是
///不起作用的
///
公共接口IMessageServiceClient
{
event System.EventHandler GetMessageCompleted;
event System.EventHandler UpdateMessageCompleted;
void GetMessageAsync();
void GetMessageAsync(对象用户状态);
无效UpdateMessageAsync(字符串消息);
void UpdateMessageAsync(字符串消息,对象用户状态);
}
}
然后我只需要创建一个分部类,它扩展了服务引用生成的代理类:
using System;
using HelloWorld.Interfaces.Services;
using System.Collections.Generic;
namespace HelloWorld.Core.Web.Services
{
public partial class HelloWorldMessageServiceClient : IMessageServiceClient
{
#region IMessageServiceClient Members
private event EventHandler<GetMessageCompletedEventArgsAdapter> handler;
private Dictionary<EventHandler<GetMessageCompletedEventArgsAdapter>, EventHandler<GetMessageCompletedEventArgs>> handlerDictionary
= new Dictionary<EventHandler<GetMessageCompletedEventArgsAdapter>, EventHandler<GetMessageCompletedEventArgs>>();
/// <remarks>
/// This is an adapter event which allows us to apply the IMessageServiceClient
/// interface to our MessageServiceClient. This way we can decouple our modules
/// from the implementation
/// </remarks>
event EventHandler<GetMessageCompletedEventArgsAdapter> IMessageServiceClient.GetMessageCompleted
{
add
{
handler += value;
EventHandler<GetMessageCompletedEventArgs> linkedhandler = new EventHandler<GetMessageCompletedEventArgs>(HelloWorldMessageServiceClient_GetMessageCompleted);
this.GetMessageCompleted += linkedhandler;
handlerDictionary.Add(value, linkedhandler);
}
remove
{
handler -= value;
EventHandler<GetMessageCompletedEventArgs> linkedhandler = handlerDictionary[value];
this.GetMessageCompleted -= linkedhandler;
handlerDictionary.Remove(value);
}
}
void HelloWorldMessageServiceClient_GetMessageCompleted(object sender, GetMessageCompletedEventArgs e)
{
if (this.handler == null)
return;
this.handler(sender, new GetMessageCompletedEventArgsAdapter(new object[] { e.Result }, e.Error, e.Cancelled, e.UserState));
}
#endregion
}
}
使用系统;
使用HelloWorld.Interfaces.Services;
使用System.Collections.Generic;
命名空间HelloWorld.Core.Web.Services
{
公共部分类HelloWorldMessageServiceClient:IMessageServiceClient
{
#区域IMessageService客户端成员
私有事件处理程序;
私人词典
=新字典();
///
///这是一个适配器事件,允许我们应用IMessageServiceClient
///接口到我们的MessageServiceClient。这样我们可以解耦模块
///从实施开始
///
事件处理程序IMessageServiceClient.GetMessageCompleted
{
添加
{
handler+=值;
EventHandler linkedhandler=新的EventHandler(HelloWorldMessageServiceClient\u GetMessageCompleted);
this.GetMessageCompleted+=linkedhandler;
Add(value,linkedhandler);
}
去除
{
handler-=值;
EventHandler linkedhandler=handlerDictionary[value];
this.GetMessageCompleted-=linkedhandler;
handlerDictionary.Remove(值);
}
}
void HelloWorldMessageServiceClient_GetMessageCompleted(对象发送方,GetMessageCompletedEventArgs e)
{
if(this.handler==null)
返回;
这个.handler(发送者,新的GetMessageCompletedEventArgsAdapter(新对象[]{e.Result},e.Error,e.Cancelled,e.UserState));
}
#端区
}
}
这是事件处理程序的显式实现,因此我可以将事件链接在一起。当用户注册我的适配器事件时,我注册实际触发的事件。当事件激发时,我激发适配器事件。到目前为止,这个“在我的机器上工作”。好的,我整天都在处理这个问题,解决方案其实要简单得多。我最初想调用接口上的方法,而不是concreate类。代理类生成器生成的接口仅包括
BeginXXX
和EndXXX
方法,调用EndXXX
时出现异常
嗯,我刚刚读完了System.Threading.Dispatcher
,终于明白了如何使用它Dispatcher
是从DispatcherObject
继承的任何类的成员,UI元素就是这样做的。Dispatcher
在UI线程上运行,对于大多数WPF应用程序,UI线程只有一个。也有例外,但我相信你必须明确地这样做,这样你才能知道你是否在这样做。否则,您只有一个UI线程。因此,在非UI类中存储对Dispatcher的引用是安全的
在我的例子中,我使用的是Prism,我的演示者需要更新UI(不是直接更新,而是触发IPropertyChanged.PropertyChanged
事件)。因此,当我将shell设置为Application.Current.RootVisual时,我所做的是在我的引导程序中,我还存储了对调度程序的引用,如下所示:
public class Bootstrapper : UnityBootstrapper
{
protected override IModuleCatalog GetModuleCatalog()
{
// setup module catalog
}
protected override DependencyObject CreateShell()
{
// calling Resolve instead of directly initing allows use of dependency injection
Shell shell = Container.Resolve<Shell>();
Application.Current.RootVisual = shell;
Container.RegisterInstance<Dispatcher>(shell.Dispatcher);
return shell;
}
}
这就简单多了。我只是不知道
public class Bootstrapper : UnityBootstrapper
{
protected override IModuleCatalog GetModuleCatalog()
{
// setup module catalog
}
protected override DependencyObject CreateShell()
{
// calling Resolve instead of directly initing allows use of dependency injection
Shell shell = Container.Resolve<Shell>();
Application.Current.RootVisual = shell;
Container.RegisterInstance<Dispatcher>(shell.Dispatcher);
return shell;
}
}
_service.BeginGetMessage(new AsyncCallback(GetMessageAsyncComplete), null);
private void GetMessageAsyncComplete(IAsyncResult result)
{
string output = _service.EndGetMessage(result);
Dispatcher dispatcher = _container.Resolve<Dispatcher>();
dispatcher.BeginInvoke(() => this.Message = output);
}
{
var state = new
{
CallingThread = SynchronizationContext.Current,
Callback = yourCallback
EndYourMethod = // assign delegate
};
yourService.BeginYourMethod(yourParams, WcfCallback, state);
}
private void WcfCallback(IAsyncResult asyncResult)
{
// Read the result object data to get state
// Call EndYourMethod and block until the finished
state.Context.Post(state.YourCallback, endYourMethodResultValue);
}
HelloWorldClient : IHelloWorld
public interface IHelloWorldAsync : IHelloWorld
{
void HelloWorldAsync(...);
event System.EventHandler<HelloWorldEventRgs> HelloWorldCompleted;
}
public partial class HelloWorldClient : IHelloWorldAsync {}