AOP预编织时间编织?

时间:2013-07-23 11:40:23

标签: c# compiler-construction aop postsharp

我和AOP一起玩了多年,但并没有对这些解决方案百分百满意。 具有运行时编织的AOP框架(如Spring.AOP)无法更改类的接口。 随着后编译时间像Postsharp这样的框架(任何人都知道别人吗?)你可以。 检查此示例,它将INotifyPropertyChanged实现添加到您的类。 - > http://www.postsharp.net/model/inotifypropertychanged

这个AOP功能非常棒,但你很快就遇到了麻烦...... 如果要访问主机程序集中的新接口,则无法编译, 因为编译后添加了接口。 所以你得到一个“未定义PropertyChanged” - 错误。 所以你必须通过将类分成另一个程序集来解决这个问题,这样你才能使用这些AOP优势。 我记得,我使用T4模板运行相同的“后编译时间” - 根据程序集的反射信息生成源代码。好的,所以编译后的时间有时太晚了......

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

所以它的“预编译时间AOP”。 这绝对是可能的,并且可以通过使用NRefactory作为Code Parser来完成。 此外,Visual Studio比编译后的修改要多得多。

因此,该解决方案消除了编译后编织器的缺点。 但并没有给你AOP的所有功能。但是与AOP-Framework一起,这应该是非常棒的。

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

亲切的问候,托马斯

3 个答案:

答案 0 :(得分:1)

既然你和我已经相应地使用SNAP作为一个可行的替代方案,我想我会在这里发布我们讨论的摘要,以便那些正在寻找类似解决方案的人受益。

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

答案 1 :(得分: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 { }

让我们创建一个适用于SomeInterfaceSomeInterfaceImplementation的实用程序类:

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开发团队。

答案 2 :(得分:0)

对于PostSharp,您可以使用方法Post.Cast访问在编译后时间引入的接口,该方法是一种在编译后时间验证的强制转换运算符。有关文档,请参阅http://doc.postsharp.net/postsharp-3.0/Content.aspx/PostSharp-3.0.chm/html/M_PostSharp_Post_Cast__2.htm