C# 使用标准.NET框架基本实现类AOP属性
可能重复:C# 使用标准.NET框架基本实现类AOP属性,c#,.net,attributes,aop,C#,.net,Attributes,Aop,可能重复: 我想实现这样的功能: [Atomic] public void Foo() { /* foo logic */ } 其中,[Atomic]属性是一个属性,它将函数逻辑包装在事务范围内: using(var scope = new TransactionScope()) { /* foo logic */ scope.Complete(); } 如何编写这样的属性 我以前也问过基本相同的问题,我知道这可以使用AOP来完成,但我没有提到
我想实现这样的功能:
[Atomic]
public void Foo()
{
/* foo logic */
}
其中,[Atomic]
属性是一个属性,它将函数逻辑包装在事务范围内:
using(var scope = new TransactionScope())
{
/* foo logic */
scope.Complete();
}
如何编写这样的属性
我以前也问过基本相同的问题,我知道这可以使用AOP来完成,但我没有提到我正在寻找一些最简单的概念证明实现或有用的文章,这些文章可以帮助我使用纯.NET框架编写本文(我假设使用RealProxy
和MarshalByRefObject
类型,我已经阅读了与浏览相关的问题)
我需要准确地解决这个示例。这似乎是一件基本的事情,所以我想从零开始学习如何做到这一点。现在不需要安全和灵活。属性都是元数据-这就是它们的全部 有许多工具可以利用这种元数据,但是这种工具需要知道该属性 像PostSharp这样的AOP工具读取这样的元数据,以便知道将方面编织到代码中的内容和位置
简而言之-只需编写一个
原子属性
就不会给您任何东西-您需要通过一个了解该属性的工具来传递已编译的程序集,并执行“操作”为了实现AOP,对它进行修改。这根本不是一件基本的事情。仅仅因为方法有一个属性,就不会运行额外的代码,因此没有地方放置您的事务范围
代码
您需要做的是,在应用程序启动时,使用反射来迭代程序集中每个类上的每个方法,并找到标记有AtomicAttribute
的方法,然后围绕该对象编写一个自定义代理。然后以某种方式让其他一切调用您的代理,而不是真正的实现,可能是usi支持依赖注入框架
大多数AOP框架在构建时都会这样做。例如,PostSharp在VisualStudio构建程序集之后运行。它扫描程序集并重写IL代码以包含代理和AOP拦截器。这样,程序集在运行时就可以正常运行,但IL与您最初编写的有所不同
这似乎是一件基本的事情
这是(许多)容易理解概念但根本不容易实现的事情之一
根据,属性在.NET中不起任何作用。它们的存在只是为了其他代码(或开发人员)可以在以后查看它们。请将其视为一个奇特的注释
记住这一点,您可以这样编写属性
public class AtomicAttribute : Attribute { }
现在最困难的部分是,您必须编写一些代码来扫描该属性,并更改代码的行为
考虑到C#是一种编译语言,并且考虑到.NET CLR的规则,理论上有三种方法可以做到这一点
这似乎很好,但根本不可能 现在,也许是 project将来可能会允许这样做,但现在,您不能这样做
基本上就是这样做的。扫描和重写MSIL很困难。有这样的库可以提供帮助,但这仍然是一个非常困难的问题。它还可能干扰调试器,等等
这可能是最简单的选择(尽管仍然非常困难),但缺点是您的程序现在必须在探查器下运行。这在您的开发PC上可能很好,但如果您尝试部署它,将导致一个巨大的问题。此外,使用此方法可能会对性能造成很大的影响
public static class Ext
{
public static void Atomic(Action action)
{
using(var scope = new TransactionScope())
{
action();
scope.Commit();
}
}
}
.....
using static Ext; // as of VS2015
public void Foo()
{
Atomic(() => {
// foo logic
}
}
这方面的计算机科学术语是也许可以使用IoC容器解析所有对象? 您可以为您的类型配置拦截器,并在拦截器中检查调用的方法是否用该属性修饰。您可以缓存该信息,这样您就不必在每次方法调用时使用反射 所以当你这样做的时候:
var something = IoC.Resolve<ISomething>();
var something=IoC.Resolve();
something
不是您已经实现的对象,而是代理。在该代理中,您可以在方法调用之前和之后执行任何您想要的操作。如果您这样做是为了自己的教育,这很好,但是如果您这样做是为了解决业务需求,那么它已经在WCF和COM+中为您完成了。谢谢您的时间。我是sta现在我想知道我真正想问的是什么。关于。属性不起任何作用并不完全正确。请看System.Web.Http.AuthorizationAttribute,它处理请求的IPPrincipal的授权。@Polymorphix不,System.Web.Http.AuthorizationAttribute也不起任何作用。当ASP.NET Web API执行它的框架工作时创建类的实例时,它会查找AuthorizeAttribute,如果看到它,它的行为会有所不同,但该属性本身只是坐在那里等待别人查找it@OrionEdwards是的,你完全正确。我的错。@OrionEdwards-关于如何嵌套作用域有什么线索吗?假设我有另一个方法w/c调用Ext.Atomic并在该方法内我会打电话给Foo。我想了解一下这个领域的一些细节,以扩展我对框架的理解,并做一些你在第二段中提到的基本工作。谢谢你的回答。我认为现代程序使用一个IOC容器。所以,这是一条路。看看哪一个是使用代理的AOP,哪一个是中间接受者a