使用标准 .NET Framework 的 AOP 类属性的基本实现 [英] Basic implementation of AOP like attribute using standard .NET Framework

查看:62
本文介绍了使用标准 .NET Framework 的 AOP 类属性的基本实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能的重复:
C# 通过属性包装方法

我想实现这样的功能:

[Atomic]
public void Foo()
{           
    /* foo logic */
}

其中[Atomic]属性是一个属性,将函数逻辑封装在一个事务范围内:

Where [Atomic] attribute is an attribute, which wraps function logic within a transaction scope:

using(var scope = new TransactionScope())
{
    /* foo logic */
    scope.Complete();
}

这样的属性怎么写?

我之前问过基本相同的问题,我知道这可以使用 AOP 来完成,但我没有提到我正在寻找一些最简单的概念实现证明或有用的文章,它们可以帮助我使用纯 .NET 框架来编写它(我假设使用 RealProxyMarshalByRefObject 类型,我已经阅读了浏览相关问题).

I've asked before basically the same question, I know this can be done using AOP, but I didn't mention I'm searching for some simplest proof of concept implementation or helpful articles which can help me to write this using pure .NET Framework (I suppose using RealProxy and MarshalByRefObject types, about which I've read browsing related questions).

我需要准确地解决这个显示的例子.这似乎是一件基本的事情,所以我想学习如何从头开始.现在不需要安全和灵活.

I need to solve exactly this shown example. It seems like a basic thing so I want to learn how to do it starting from scratch. It doesn't need to be safe and flexible for now.

推荐答案

这似乎是一件基本的事情...

It seems like a basic thing...

这是(许多)简单理解概念但实施起来却并不简单的事情之一.

It's one of the (many) things which are simple to understand the concept, but not at all simple to implement.

根据 Oded 的回答,.NET 中的属性不会做任何事情.它们只是存在以便其他代码(或开发人员)可以稍后查看它们.把它想象成一个花哨的评论.

As per Oded's answer, Attributes in .NET don't do anything. They only exist so that other code (or developers) can look at them later on. Think of it as a fancy comment.

考虑到这一点,您可以像这样编写属性

With that in mind, you can write your attribute like this

public class AtomicAttribute : Attribute { } 

现在是困难的部分,您必须编写一些代码来扫描该属性,并更改代码的行为.

Now the hard part, you have to write some code to scan for that attribute, and change the behaviour of the code.

鉴于 C# 是一种编译语言,并且鉴于 .NET CLR 的规则,理论上有 3 种方法可以做到这一点

Given that C# is a compiled language, and given the rules of the .NET CLR there are theoretically 3 ways to do this

  1. 挂钩 C# 编译器,并使其在看到该属性时输出不同的代码.
    这似乎很好,但这是不可能的马上.也许罗斯林项目将来可能会允许这样做,但目前您不能这样做.

  1. Hook into the C# compiler, and make it output different code when it sees that attribute.
    This seems like it would be nice, but it is simply not possible right now. Perhaps the Roslyn project might allow this in future, but for now, you can't do it.

编写一些内容,在 C# 编译器将其转换为 MSIL 并更改 MSIL 之后扫描 .NET 程序集.
这基本上是 PostSharp 所做的.扫描和重写 MSIL 很难.有诸如 Mono.Cecil 之类的库可以提供帮助,但这仍然是一个非常困难的问题.它还可能会干扰调试器等.

Write something which will scan the .NET assembly after the C# compiler has converted it to MSIL, and change the MSIL.
This is basically what PostSharp does. Scanning and rewriting MSIL is hard. There are libraries such as Mono.Cecil which can help, but it's still a hugely difficult problem. It may also interfere with the debugger, etc.

在程序运行时使用 .NET Profiling API 监视程序,并且每次看到具有该属性的函数调用时,将其重定向到其他一些包装函数.
这可能是最简单的选择(尽管它仍然非常困难),但缺点是您的程序现在必须在分析器下运行.这在您的开发 PC 上可能没问题,但如果您尝试部署它,则会导致一个大问题.此外,使用这种方法可能会对性能造成很大影响.

Use the .NET Profiling API's to monitor the program while it is running, and every time you see a function call with that attribute, redirect it to some other wrapper function.
This is perhaps the simplest option (although it's still very difficult), but the drawback is that your program now must be run under the profiler. This may be fine on your development PC, but it will cause a huge problem if you try deploy it. Also, there is likely to be a large performance hit using this approach.

在我看来,最好的办法是创建一个设置事务的包装函数,然后传递一个执行实际工作的 lambda.像这样:

In my opinion, your best bet is to create a wrapper function which sets up the transaction, and then pass it a lambda which does the actual work. Like this:

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
    }
}

这个花哨的计算机科学术语是高阶编程

The fancy computer science term for this is Higher order programming

这篇关于使用标准 .NET Framework 的 AOP 类属性的基本实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆