我在 View 模型中订阅了一个事件。事件订阅是在通过 Unity 创建的 View 模型的构造函数中完成的。
我发现如果我订阅为:
showViewAEvent.Subscribe(ShowViewAHasBeenRequested) 或 showViewAEvent.Subscribe(ShowViewAHasBeenRequested, False) 我收到以下错误:
// {System.MethodAccessException: ModuleA.Views.ModuleAViewModel.ShowViewAHasBeenRequested(Boolean)
//at System.Delegate.BindToMethodInfo(Object target, RuntimeMethodHandle method, RuntimeTypeHandle methodType, DelegateBindingFlags flags)
//at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure)
//at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method)
//at Microsoft.Practices.Composite.Events.DelegateReference.TryGetDelegate()
//at Microsoft.Practices.Composite.Events.DelegateReference.get_Target()
//at Microsoft.Practices.Composite.Events.EventSubscription`1..ctor(IDelegateReference actionReference, IDelegateReference filterReference)
//at Microsoft.Practices.Composite.Presentation.Events.CompositePresentationEvent`1.Subscribe(Action`1 action, ThreadOption threadOption, Boolean keepSubscriberReferenceAlive, Predicate`1 filter)
//at Microsoft.Practices.Composite.Presentation.Events.CompositePresentationEvent`1.Subscribe(Action`1 action, ThreadOption threadOption, Boolean keepSubscriberReferenceAlive)
//at Microsoft.Practices.Composite.Presentation.Events.CompositePresentationEvent`1.Subscribe(Action`1 action, Boolean keepSubscriberReferenceAlive)
//at ModuleA.Views.ModuleAViewModel..ctor(IEventAggregator eventAggregator, IRegionManager regionManager)
//at BuildUp_ModuleA.Views.ModuleAViewModel(IBuilderContext )
//at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
//at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
//at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)}
但是,如果我在事件订阅上将标志设置为 true,则不会收到错误。
由于我是 prism 的新手,我仍在尝试确定是否在正确的位置创建订阅。
京东。
最佳答案
这是一个已知问题,此处有完整记录:
http://compositewpf.codeplex.com/WorkItem/View.aspx?WorkItemId=4925
CompositePresentationEvent<>.Subscribe() 中的错误可防止弱事件引用标题为必填项
描述 描述为必填项 概述:
此类的 Subscribe() 方法被记录为默认创建 WeakReferences,或者在包含该参数的重载中指定为 keepSubscriberReferenceAlive=false 时。
详细信息:
只有在提供过滤器委托(delegate)时才能正确观察到此行为。在所有其他情况下(以及 Subscribe() 方法的所有重载),都会创建强引用 - 无论记录的默认值如何,也无论为 keepSubscriberReferenceAlive 参数提供的任何值如何。
此错误的根源可以在该方法的以下重载中找到:
CompositePresentationEvent.Subscribe(操作操作,ThreadOption threadOption,bool keepSubscriberReferenceAlive,谓词过滤器)
在此方法中,检查“filter”参数。如果过滤器不为空,则处理会正确继续。但是,如果此参数为 null,则创建一个新的传递委托(delegate)(始终返回 true)并将其用于过滤器。该错误在于,从此传递委托(delegate)创建的 DelegateReference 对象将 keepReferenceAlive 参数硬编码为值“true”。该值不应被硬编码,而应传递传入参数 keepSubscriberReferenceAlive。
解决方法:
此问题有一个简单的解决方法。注册订阅时,您应该始终使用上述详细重载,并始终提供过滤器委托(delegate)。切勿为过滤器参数传递“null”。如果不应过滤订阅,则在需要弱事件引用时应使用传递过滤器委托(delegate)(典型场景):
EventAggregator.GetEvent().Subscribe(MyHandler, ThreadOption.PublisherThread, false, (dummy) => true);
以下缩写重载没有解决方法,并且在修补底层错误之前不应使用这些重载:
CompositePresentationEvent.Subscribe(操作操作) CompositePresentationEvent.Subscribe(Action 操作,ThreadOption threadOption) CompositePresentationEvent.Subscribe(Action 操作,bool keepSubscriberReferenceAlive) CompositePresentationEvent.Subscribe(Action action, ThreadOption threadOption, bool keepSubscriberReferenceAlive)
关于silverlight - 使用 Prism 进行事件订阅,给出方法访问异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1637720/