这是线程安全的吗?
Prism中的EventAggregator是一个非常简单的类,只有一个方法.当我注意到null检查没有锁定并创建一个新类型以添加到private _events集合时,我感到很惊讶.如果两个线程同时为同一类型调用GetEvent(在_events中存在之前),则看起来这将导致集合中的两个条目.
/// <summary>
/// Gets the single instance of the event managed by this EventAggregator. Multiple calls to this method with the same <typeparamref name="TEventType"/> returns the same event instance.
/// </summary>
/// <typeparam name="TEventType">The type of event to get. This must inherit from <see cref="EventBase"/>.</typeparam>
/// <returns>A singleton instance of an event object of type <typeparamref name="TEventType"/>.</returns>
public TEventType GetEvent<TEventType>() where TEventType : EventBase
{
TEventType eventInstance = _events.FirstOrDefault(evt => evt.GetType() == typeof(TEventType)) as TEventType;
if (eventInstance …Run Code Online (Sandbox Code Playgroud) 我需要一些关于如何在单元测试中使用Moq的建议,以确保我所测试的课程表现得如何.那就是被测试的类发布了一个Event Aggregator(来自Prism)事件,我需要一些方法断言在我的测试中引发了这个事件.
我没有很多工作资源,我发现很难知道如何设置它.
我有 :-
public SomeEvent : CompositePresentationEvent<SomeEvent>
{
EventPayload
}
public SomeClass
{
void Allocate(){EventAggregator.Publish<SomeEvent>}
}
public SomeService : IService
{
SomeService(){ EventAggregator.Subscribe<SomeEvent>(DoSomething)}
void DoSomething(SomeEvent evt){}
}
Run Code Online (Sandbox Code Playgroud)
我认为,如果我的测试是针对SomeClass的,我需要验证如果我调用SomeClass.Allocate正在发布SomeEvent消息.这是怎么做到的?
我是否还需要验证模拟的SomeService是否正在接收SomeEvent?或者这是一个单独的单元测试属于SomeService单元测试而不是SomeClass?
无论如何,不知道如何设置任何这样的任何建议将不胜感激.
为了简单的模块间通信,存在经典.NET事件,但现在有太多事件,并且存在通过模块相互调用的事件链.
就像Event_A触发Event_B时触发Event_C.
这EventAggregator对于一个模块中的解耦通信非常方便,所以我尝试了一个小的"Jon Skeet Singleton IV" EventAggregator来打破这些event链.关于C#单身人士的Jon Skeet可以在这里找到
他告诉它是线程安全的,但他的例子只是暴露了一个Singleton资源.
这是我的代码
public static class GlobalEventAggregator
{
private static readonly IEventAggregator EventAggregator = new EventAggregator();
// tell C# compiler not to mark type as beforefieldinit
static GlobalEventAggregator()
{
}
public static void Subscribe(object instance)
{
EventAggregator.Subscribe(instance);
}
public static void Unsubscribe(object instance)
{
EventAggregator.Unsubscribe(instance);
}
public static void Publish(object message)
{
EventAggregator.Publish(message);
}
}
Run Code Online (Sandbox Code Playgroud)
现在我可以GlobalEventAggregator在每个模块中使用它来发布事件,并且对这些事件感兴趣的每个其他模块都可以愉快地处理它们.没有更多的链接.
但是我会遇到多线程问题吗? …
鉴于以下场景:
Is it bad to simply inject ViewModelA into ViewModelB via constructor injection and just set the property directly?
Or…
Should a messaging system like the EventAggregator from Prism be used to handle all communication between ViewModels?
I like the injection approach because it’s easy, but my instincts are telling me I’m missing something. I call on your collective wisdom to help fill in …
dependency-injection inversion-of-control mvvm viewmodel eventaggregator
我是MVVW模式的新手,所以如果我问一个非常基本的问题,你将不得不原谅我.
我有两个ViewModel,我们称之为TreeViewViewModel和ListViewViewModel.TreeViewViewModel在其视图中绑定到IsSelected属性.每当IsSelected更改时,我都需要通知ListViewViewModel以便它可以更新它的视图.
经过一些网上研究,我遇到了EventAggregator,看起来它可能是一个很好的解决方案.
这是正确的解决方案吗?如果是这样,我该如何实施呢?或者,我应该考虑更好的解决方案吗?下面是我认为可以将EventAggregator集成到发布事件的ViewModel中的简化版本.
public class TreeViewViewModel : INotifyPropertyChanged
{
public bool IsSelected
{
get { return _isSelected; }
set
{
if (value == _isSelected)
return;
_isSelected = value;
OnPropertyChanged("IsSelected");
// Is this sane?
_eventAggregator.GetEvent<TreeViewItemSelectedEvent>().Publish(value);
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Run Code Online (Sandbox Code Playgroud) 我有以下设置:
我使用MEF作为DI框架来连接我的应用程序的各个部分.
我有2个地区:
一个(左侧)填充了列表视图(例如客户)
其中一个(右侧)填充了一个视图,其中包含一个tabcontrol,其中包含我填充的区域(根据选择的客户),另一个视图包含带有区域的选项卡控件.
右侧结果:

为了填充第一级tabcontrol我正在听"客户更改的事件" - (这很好用)当我收到事件时,我用Views填充First Level选项卡区域:
Dim lReg As IRegion = Me.mRegionManager.Regions("FirstLevelTabReqion")
Dim lViewID As String = CommonDefinitions.Constants.BuildFirstLevelViewName(lUniqueID)
Dim lFirstLevelView FirstLevelView = TryCast(lReg.GetView(lRqViewID), FirstLevelView)
If lFirstLevelView Is Nothing Then
lFirstLevelView = New FirstLevelView()
Dim lRegMan1 As IRegionManager = lReg.Add(lFirstLevelView, lViewID, True)
lFirstLevelView.SetRegionManager(lRegMan1)
...
End If
Run Code Online (Sandbox Code Playgroud)
注意:创建FirstLevelView时,我必须CompositionInitializer.SatisfyImports调用以确保FirstLevelView解析其ViewModel引用.
要在SecondLevel ViewModel中获取EventsAggregator的实例,我使用:
<ImportingConstructor()>
Public Sub New(ByVal iEvAggregator As IEventAggregator)
EventAggregator = iEvAggregator
EventAggregator.GetEvent(Of DoStuffSecondLevel).Subscribe(AddressOf OnDoStuffSecondLevel, True)
End Sub
Run Code Online (Sandbox Code Playgroud)
我的问题是我在第二级视图模型中获得的EventAggregator实例与第一级中的EventAggregator实例不同,因此如果我在第一级发布DoStuffSecondLevel,它将不会在第二级捕获.
为什么我会得到2个不同的EventAggregator实例?
如何在整个应用程序中共享相同的EventAggregator实例?
提前致谢
我正在使用MVVM和WPF项目Microsoft Prism libraries.所以,当我需要通过类进行通信时,我使用该类Microsoft.Practices.Prism.MefExtensions.Events.MefEventAggregator,我发布事件和订阅方法如下:
要发布:
myEventAggregator.GetEvent<MyEvent>().Publish(myParams)
认购:
myEventAggregator.GetEvent<MyEvent>().Subscribe(MySubscribedMethod)
但我的问题是:有没有办法在发布事件后从"订阅方法"返回一些数据?
我应该何时使用事件处理程序而不是事件聚合器?
在我的代码中,我有两个由父ViewModel控制的ViewModel,我试图决定是否应该使用事件处理程序在它们之间进行通信?或者使用Event Aggregator?它只是简单的方法调用,我不需要在它们之间传递参数.
我花了最近两周的时间学习骨干和相关工具以及编写应用程序.我遇到了设计问题,想知道可用的解决方案类型,以及Backbone专家是否认为这是一个问题.
问题:我最终不得不将所有视图依赖项放在我的router.js中,并且无法弄清楚它们是否是一种方法.以下是我的router.js的代码:
// router.js
define([
'jquery',
'underscore',
'backbone',
'text',
'views/landing',
'views/dashboard',
],
function($, _, Backbone, t,LandingView,DashboardView){
var AppRouter = Backbone.Router.extend({
routes: {
// Define some URL routes
'': 'showLanding',
'projects': 'showProjects',
// Default
'*actions': 'defaultAction'
},
navigate_to: function(model){
alert("navigate_to");
},
showProjects: function() {},
showLanding: function() {},
});
var initialize = function() {
var app_router = new AppRouter;
Backbone.View.prototype.event_aggregator = _.extend({}, Backbone.Events);
// Extend the View class to include a navigation method goTo
Backbone.View.prototype.goTo = function (loc) {
app_router.navigate(loc, true);
}; …Run Code Online (Sandbox Code Playgroud) javascript design-patterns eventaggregator backbone.js marionette
从Symfony2的EventDispatcher组件文档:
Symfony2 EventDispatcher组件以简单有效的方式实现Mediator模式,使所有这些事情成为可能,并使您的项目真正可扩展.
我一直在阅读有关Event Aggregator和Mediator模式及其差异的内容.对我而言,事件聚合器看起来像是Mediator的一个特例,它使用事件来促进沟通,并且内部没有任何业务逻辑.另一方面,Mediator更通用,并且可以允许一些业务逻辑来决定是否应该进行某些通信.
所以我检查了Symfony2的EventDispatcher或TraceableEventDispatcher的源代码,发现可能改变通信的唯一逻辑是检查事件传播是否已经停止,如下所示:
protected function doDispatch($listeners, $eventName, Event $event)
{
foreach ($listeners as $listener) {
call_user_func($listener, $event, $eventName, $this);
if ($event->isPropagationStopped()) {
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是为什么Symfony2中的EventDispatcher实现Mediator模式而不是Event Aggregator模式的原因?如果要检查的逻辑isPropagationStopped被移出EventDispatcher(比如说,移到事件监听器),那么这会实现Event Aggregator吗?
eventaggregator ×10
wpf ×4
mvvm ×3
prism ×3
c# ×2
events ×2
silverlight ×2
viewmodel ×2
.net ×1
backbone.js ×1
javascript ×1
marionette ×1
mediator ×1
mef ×1
mocking ×1
moq ×1
nunit ×1
php ×1
symfony ×1
unit-testing ×1