使用棱镜的事件订阅给出methodaccess异常

时间:2009-10-28 14:43:06

标签: silverlight prism

我在视图模型中订阅了一个事件。事件订阅在视图模型的构造函数中完成,该构造函数通过unity创建。

我发现如果我订阅:

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,则不会收到错误。

由于我是棱镜新手,如果我在正确的位置创建订阅,我仍在努力解决。

JD。

5 个答案:

答案 0 :(得分:4)

这是一个众所周知的问题:

http://compositewpf.codeplex.com/WorkItem/View.aspx?WorkItemId=4925

CompositePresentationEvent中的错误<> .Subscribe()会阻止弱事件引用标题是必需的

描述描述是必需的 概述:

此类的Subscribe()方法记录为默认创建WeakReferences或在包含该参数的重载中指定为keepSubscriberReferenceAlive = false。

详情:

仅在提供过滤器委托时才能正确观察到此行为。在所有其他情况下(以及Subscribe()方法的所有重载),都会创建一个强引用 - 无论记录的默认值如何,也不管keepSubscriberReferenceAlive参数的任何提供值。

此错误的来源可以在此方法的以下重载中找到:

CompositePresentationEvent.Subscribe(Action action,ThreadOption threadOption,bool keepSubscriberReferenceAlive,Predicate filter)

在此方法中,检查“过滤器”参数。如果过滤器不为null,则处理继续正确。但是,如果此参数为null,则会创建一个新的传递委托(始终返回true)并将其用于过滤器。错误是从此传递委托创建的DelegateReference对象将keepReferenceAlive参数硬编码为值“true”。此值不应该是硬编码的,而应传递传入参数keepSubscriberReferenceAlive。

替代方法:

此问题有一个简单的解决方法。注册订阅时,应始终使用上述详细过载,并始终提供过滤器委托。永远不要为filter参数传递“null”。如果不应过滤订阅,则在需要弱事件引用时应使用传递过滤器委托(典型情况):

EventAggregator.GetEvent()。订阅(MyHandler,ThreadOption.PublisherThread,false,(dummy)=> true);

以下缩写重载没有解决方法,在修补基础错误之前不应使用这些重载:

CompositePresentationEvent.Subscribe(动作动作) CompositePresentationEvent.Subscribe(Action action,ThreadOption threadOption) CompositePresentationEvent.Subscribe(动作动作,bool keepSubscriberReferenceAlive) CompositePresentationEvent.Subscribe(Action action,ThreadOption threadOption,bool keepSubscriberReferenceAlive)

答案 1 :(得分:1)

经过进一步研究,我找到了这个帖子: http://compositewpf.codeplex.com/Thread/View.aspx?ThreadId=57362

我没有意识到订阅电话实际上是在CallStack中,或者我之前会意识到这一点。这是一段摘录:

  

Silverlight不支持弱   对lambda表达式的引用或   匿名代表。因此,   filter参数必须是单独的   如果您是定位方法   的Silverlight。

您是否尝试使用lambda作为该订阅的处理程序?如果是这样,看起来您需要做的就是使用真实的方法。

EventService.GetEvent<GenericEvent<string>>().Subscribe(YourAction)

.....

public void YourAction(string topic)
{
   if(topic == "something")
   {
      // more code
   }
}

答案 2 :(得分:1)

ShowViewAHasBeenRequested方法是公开的吗?如果没有,调用代码将无法访问它。

答案 3 :(得分:0)

发布事件时,您的ViewModel是否超出了范围?在Subscribe方法中传递True会创建一个强引用,这会使订阅者在超出范围后不会获得GC。了解这样做会造成内存泄漏,因为您实例化的每个ViewModel都将继续存在并响应那些已发布的事件。

在我的Module的Initialize方法中设置一些事件订阅时遇到了同样的问题 - 据我所知,在完成所有设置之后,没有任何东西正在保存对我的模块的引用。

答案 4 :(得分:0)

我有完全相同的问题并通过根据用户188067和Konamiman的响应公开过滤方法和操作方法来解决它。即。

showViewAEvent.Subscribe(ShowViewAHasBeenRequested, ThreadOption.UIThread, false, ShouldHandleEvent);

public bool ShouldHandleError(object obj)
{
    return true;
}

public void ShowViewAHasBeenRequested(object obj)
{
...
}