好,
这是一个更普遍的"角落里丑陋的生物"问题.我打算开始一个关于WCF和PRISM的项目.有一段时间我一直在玩PRISM,并且必须说,我喜欢它.具有良好发展可能性的应用的坚实基础.
现在我想要合并WCF并构建一个分布式应用程序,其中一个部分在服务器上,两个在客户端上.根据情况,它可能是相同的机器,也可能不是.
我现在的想法是从PRISM中获取事件概念并使用WCF和回调"通过线路"扩展它,如此处所述的WCF AlarmClock回调示例.
我创建了一张小图片来说明这个想法(主要是针对我),也许这会使事情变得更加清晰:

灰色箭头代表"使用lib".WCF-Event-Base意味着正常的PRISM事件,其中发布方法被称为"通过线路".
有几个问题浮现在脑海中:
关于第二个问题,我目前考虑使用字符串(我想要提出的具体事件的类型)和有效负载作为参数来提升事件.像public void RaiseEvent(string eventType, object eventPayload){}有效载荷这样的东西需要可序列化,也许我甚至包括一个hashcheck.(意思是如果我举起例如一个带有图片作为参数的事件10次,我只转移图片一次,之后使用哈希让服务器在发布时使用缓冲区)...
好的,我想你明白了.这个"东西"应该像一个巨大的单一应用程序,使用一种WCF_EventAggregator而不是普通的PRISM IEventAggregato r.(哇,写作的时候,我只是想"简单地"扩展IEventAggregator,不得不考虑这个)...
为什么我这样写?好吧,主要是反馈,并对我的想法进行排序.所以评论欢迎,或许我应该"小心"的任何事情?
克里斯
[EDITS]
应该有一个未定义的客户端数量,服务器不应该知道客户端.服务器本身可以是自身的客户端,在源代码的其他部分引发强类型的PRISM事件.
"客户端"和"服务器"之间的主要区别是WCF_PRISM连接器的实际实现,请参阅下一章......
在PRISM中,要提出简单事件,您甚至不需要引用服务接口.IEventAggregator可以通过依赖注入获得,提供所需事件的实例(例如WeatherChangedEvent).只需调用eventInstance.Publish(23)就可以引发此事件,因为事件实现为public class WeatherChangedEvent : CompositePresentationEvent<int>
提升事件就像订阅事件一样简单.每个模块都可以使用相同的技术来获取事件,获取引用并使用Subscribe附加到此事件.
现在这里应该发生"魔术".客户端将包括一个棱镜模块,负责将PRISM事件连接到"wcf消息发送".它基本上将属于解决方案中的所有可用事件(它们都在基础结构模块中定义)并在发生事件时发送WCF消息.
SERVER和CLIENT之间的区别在于该模块的实现.由于两件事,需要略有不同.
事件流程将是(示例)
显而易见的是阻止循环.如果服务器将在所有客户端中引发事件,则客户端将回调服务器,再次引发事件,依此类推......因此,本地引发的事件之间需要存在差异(这意味着我必须发送它到服务器)和"服务器引起的事件",这意味着我不必将其发送到服务器.
此外,如果客户端本身已启动事件,则不需要服务器调用它,因为事件已经被引发(在客户端本身,第2点).
所有这些特殊行为都将封装在WCF事件提升器模块中,从应用程序的其余部分看不到.我必须考虑"如何知道事件是否已经发布",也许GUID或类似的东西是个好主意.
现在是第二个大问题,我早些时候在讲述"字符串"时的目的是什么.每次添加事件时,我都不想编写新的服务接口定义.PRISM中的大多数事件都由一行定义,特别是在开发过程中我不希望每次添加事件时都更新WCF_Event_Raising_Module.
我想在调用WCF时直接发送事件,例如使用带有以下签名的函数:
public void RaiseEvent(EventBase e, object[] args)
Run Code Online (Sandbox Code Playgroud)
问题是,我真的不知道我是否可以轻松地序列化PRISM事件.它们都来自EventBase,但我必须检查一下......出于这个原因,我有想法使用类型(作为字符串),因为我知道服务器共享基础结构模块并且可以获得自己的事件实例(无需通过电线发送,只需arg)
到目前为止,我将继续提出问题以获得更多反馈.我刚刚得到的主要新"洞察力":必须考虑递归/ infite循环问题.
顺便说一句.如果有人对所有这些事件的谈话感到困惑,请试试PRISM.你会喜欢它,即使你只使用DI和事件(RegionManager,例如不是我最喜欢的)
克里斯
[结束编辑1]
这是一个非常有趣的方法.我在这里只说两件事:
我认为你所做的是可行的.看看你的实现,我真的很喜欢你的想法.
我想在那里扔一些东西,看看你对它的看法......也许它会稍微影响你的设计.具体来说,这是为了解决我上面的第一点,并进一步强调打字.
您是否考虑过使用EventAggregator支持的服务接口实现?假设您的示例中包含您正在使用的IWeatherService WCF服务.目前,据我了解,您的用法将如下所示:
为什么不稍微修改一下.使IWeatherService成为所有服务器和客户端之间的共享契约.显然,服务器将具有实际的实现,但客户端将具有EventAggregator支持的实现,这些实现将转发到中央代理,该代理将消息排队并发送到服务器.
编写一个由EventAggregator支持的IWeatherService实现,该实现引发由中央消息代理接收的事件,并将该实现抛出到容器中供客户端使用.
public ClientWeatherService : IWeatherService
{
IEventAggregator _aggregator;
public ClientWeatherService(IEventAggregator aggregator)
{
_aggregator = aggregator;
}
public void ChangeWeather(Weather weather)
{
ChangeWeatherEvent cwEvent = _aggregator.GetEvent<ChangeWeatherEvent>();
cwEvent.Publish(weather);
}
}
Run Code Online (Sandbox Code Playgroud)
从那里,他们不直接使用"WCF事件客户端库",而是直接使用IWeatherService,而不知道它不会调用实际服务.
public MyWeatherViewModel : ViewModel
{
IWeatherService _weatherService;
public MyWeatherViewModel(IWeatherService weatherService)
{
_weatherService = weatherService;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您将设置一些事件处理程序以使WCF调用实际服务,但现在您可以从客户端进行强类型操作.
只是一个想法.
我真的很喜欢这类问题.我希望更多的人会在Stackoverflow上问这种事情.让大脑在早上移动:)
这似乎是一个解决问题的复杂方法。
您是从客户端应用程序引发事件,还是使用回调合约从服务引发事件?或两者?
我会在客户端中通过一个简单的服务类来解决这个问题。它可以实现回调合约,并且对于每个回调方法,它可以在本地向客户端中的任何订阅者引发 Prism 事件。如果您需要引发由服务处理的事件,则服务类可以订阅这些事件并调用 wcf 服务。
您真正需要的只是一个从客户端抽象出 wcf 服务详细信息的类,并通过 Prism 事件公开其接口。
我个人不想修改/扩展基础设施组件并创建对具体 wcf 服务的依赖。