AOP预编译时编织?

问题描述 投票:0回答:3

我已经使用 AOP 多年了,但对解决方案并没有 100% 满意。 具有运行时编织的 AOP 框架(如 Spring.AOP)无法更改类的接口。 使用像 Postsharp 这样的编译后框架(有人认识其他人吗?),你可以。 查看此示例,它将 INotifyPropertyChanged 实现添加到您的类中。 -> http://www.postsharp.net/model/inotifypropertychanged

这个 AOP 功能确实很棒,但是你很快就会遇到麻烦...... 如果要访问托管程序集中的新接口,则无法编译, 因为接口是在编译后添加的。 因此您会收到“PropertyChanged 未定义”错误。 因此,您必须通过将类分离到另一个程序集中来解决这个问题,这样您就可以利用 AOP 的优势。 我记得,我遇到了同样的“编译后时间”问题——使用基于程序集的反射信息生成源代码的 T4 模板的问题。好的,所以编译后时间有时已经太晚了......

我正在寻找一种解决方案,其中类的源代码通过 Visual Studio 用户定义的工具进行解析,然后在部分类中的 C# 文件中生成代码。 (所以所有AOP应用的类都必须是偏的)

所以它是一种“预编译时 AOP”。 这绝对是可能的,并且可以通过使用 NRefactory 作为代码解析器来完成。 此外,与编译后修改相比,Visual Studio 更希望这样做。

所以这个解决方案消除了编译后编织器的缺点。 但并没有给你AOP的所有功能。但与 AOP 框架一起,这应该很棒。

有人知道这样的框架或讨论吗?! 你觉得怎么样?

亲切的问候,托马斯

c# aop postsharp
3个回答
1
投票

由于您和我已经就使用 SNAP 作为可行的替代方案进行了通信,我想我应该在这里发布我们的讨论摘要,以便那些正在寻找类似解决方案的人受益。

简而言之,SNAP提供了一个运行时 AOP 框架,不会以任何方式更改您的代码。 没有编译后步骤,只有运行时拦截,这是可预测且易于使用的。


1
投票

您正在寻找的是pMixins。 它仍处于测试阶段,但它正是您所寻找的:设计时编织。 AOP 代码生成为部分代码隐藏类,因此可以在设计时使用。

因此,这意味着您可以在一个文件中执行此操作,并且编译器很高兴,Visual Studio 很高兴,resharper 很高兴:

定义接口:

public interface ISomeInterface
{
    void SomeMethod();
}

创建接口的实现(我称之为 Mixin):

public class SomeInterfaceImplementation : ISomeInterface
{
    public void SomeMethod()
    {
        //implementation
    }
}

定义一个目标文件(它将消耗Mixin):

[pMixin(Mixin = typeof(SomeInterfaceImplementation))]
public partial class Target { }

让我们创建一个与

SomeInterface
SomeInterfaceImplementation
一起使用的实用程序类:

public class Utility
{
    public void DoSomeWorkOnSomeInterface(ISomeInterface obj)
    {
        obj.SomeMethod();
    }

    public void DoSomeWorkOnImplementation(SomeInterfaceImplementation obj)
    {
        obj.SomeMethod();
    }
}

现在让我们看看这一切如何协同工作:

class Program
{
    private static void Main(string[] args)
    {
        //Call the mixed in method
        new Target().SomeMethod();

        //Target implements ISomeInterface is code-behind
        new Utility().DoSomeWorkOnSomeInterface(new Target());

        //Target has an implicit conversion operator to 
        //SomeInterfaceImplementation in code-behind
        new Utility().DoSomeWorkOnImplementation(new Target());
    }
}

之所以有效,是因为一旦保存文件,pMixins 代码生成器就会立即进行设计时编织并更新代码隐藏文件。 它将

SomeMethod
直接添加到
Target
,更新
Target
的类定义以实现
ISomeInterface
并创建转换运算符。

披露:我是 pMixins 开发团队的成员。


0
投票

对于PostSharp,您可以使用方法

Post.Cast
访问在编译后引入的接口,该方法是一种在编译后验证的强制转换运算符。请参阅 http://doc.postsharp.net/postsharp-3.0/Content.aspx/PostSharp-3.0.chm/html/M_PostSharp_Post_Cast__2.htm 了解文档。

© www.soinside.com 2019 - 2024. All rights reserved.