PostSharp 3.0 中 IAspectProvider 的重大變化? (Breaking change of IAspectProvider in PostSharp 3.0?)


問題描述

PostSharp 3.0 中 IAspectProvider 的重大變化? (Breaking change of IAspectProvider in PostSharp 3.0?)

Today I upgraded to PostSharp 3. After some messing around with referencing the correct DLLs in my projects I compile and all seems fine, until I get a runtime exception. An aspect which has been working perfectly fine in PostSharp 2.1 now behaves differently.

It's a generic aspect applied with help of IAspectProvider. Full source can be found on GitHub.

public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
{
    Type targetType = (Type)targetElement;
    Type genericAspect = typeof( ViewModelAspect<,> ).MakeGenericType( _propertiesEnumType, _commandsEnumType );
    yield return new AspectInstance( targetType, Activator.CreateInstance( genericAspect ) as IAspect );
}

What seems to happen is the aspect with wrong generic parameters is applied to my type. When I use dotPeek to look at the post‑compiled code I see a newly introduced generic field with generic parameters which are meant to be applied on a different type. In fact, all types with the aspect applied to share the same generic parameters (and thus only one is correct).

This was working correctly before, did anything relating to IAspectProvider change in PostSharp 3 that I should think about?

For debugging purposes I already checked whether _propertiesEnumType and _commandsEnumType are set correctly at build time, and they are, thus I think something must go wrong afterwards; perhaps the created aspects being applied to the wrong instances?


Below you can see the decompiled code where PostSharp seems to be doing something wrong. The correct aspect seems to be introduced, however the property I am introducing is exposed as a different (wrong) type. Notice the ViewModel.Main as parameter of the aspect, contrasted with the ViewModel.ActivityOverview as parameter for the CommandFactory, which should be ViewModel.Main as well.

[NonSerialized]
private ViewModelAspect<Laevo.ViewModel.Main.Binding.Properties, Laevo.ViewModel.Main.Binding.Commands> \u003C\u003Ez__aspect35;

private CommandFactory<Laevo.ViewModel.ActivityOverview.Binding.Commands> CommandFactory
{
  get
  {
    return ((ViewModelAspect<Laevo.ViewModel.ActivityOverview.Binding.Properties, Laevo.ViewModel.ActivityOverview.Binding.Commands>) this.\u003C\u003Ez__aspect35).CommandFactory;
  }
}

參考解法

方法 1:

I turned out to be a bug in the new version. The updated version on NuGet fixes the issue.


Before the fix was released, I temporarily worked around it by introducing non‑generic members instead and relying on reflection a bit more at run time.

[IntroduceMember( Visibility = Visibility.Private )]
//public CommandFactory<TCommands> CommandFactory
public object CommandFactory
{
    get { return _commandFactory; }
    private set { _commandFactory = value; }
}

Notice that the incorrect conversion (it should be Laevo.ViewModel.Main in this case) is still generated by PostSharp:

private object CommandFactory
{
  get
  {
    return ((ViewModelAspect<Laevo.ViewModel.ActivityOverview.Binding.Properties, Laevo.ViewModel.ActivityOverview.Binding.Commands>) this.\u003C\u003Ez__aspect35).CommandFactory;
  }
}

However, since the correct generic aspect is created, I can cast to the correct type at run time. Everything works ... the code just got a whole lot messier (and probably slower due to relying on reflection more).

(by Steven JeurisSteven Jeuris)

參考文件

  1. Breaking change of IAspectProvider in PostSharp 3.0? (CC BY‑SA 3.0/4.0)

#postsharp #aop #C#






相關問題

拋出自定義異常並使用 Postsharp 捕獲它們 (Throw an custom exception and catch them with Postsharp)

Làm cách nào để loại trừ khỏi ghi nhật ký dựa trên OnMethodBoundaryAspect? (How to exclude from OnMethodBoundaryAspect-based logging?)

在屬性中傳遞動態參數 (PostSharp) (Passing dynamic parameters in attributes (PostSharp))

PostSharp 3.0 中 IAspectProvider 的重大變化? (Breaking change of IAspectProvider in PostSharp 3.0?)

將方面應用於其他程序集類方法調用 (apply an aspect to other assembly class methods calls)

Postsharp 和 log4net 和 log4postsharp (Postsharp and log4net and log4postsharp)

Postsharp - 獲取調用程序集? (Postsharp - Get Calling Assembly?)

PostSharp 對象映射器 (PostSharp for an object mapper)

PostSharp - 自動化事件訂閱和集合添加 (PostSharp - automate event subscription and collection addition)

PostSharp:在目標構造函數之後初始化實例範圍的方面 (PostSharp: initialize instance-scoped aspect after target constructors)

使用 PostSharp 1.0 的 ClickOnce 應用程序似乎需要 GAC 中的 1.5 程序集 (ClickOnce application that uses PostSharp 1.0 seems to require 1.5 assemblies in GAC)

更改用戶控件 DependencyProperty 時屬性重置 (Property resets when changing Usercontrols DependencyProperty)







留言討論