我和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一起,这应该是非常棒的。
有没有人知道这样的框架或讨论?! 你觉得怎么样?
亲切的问候,托马斯答案 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 { }
让我们创建一个适用于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开发团队。
答案 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。