使用标准 .NET Framework 的 AOP 类属性的基本实现 [重复]

2024-01-02

可能的重复:
C# 通过属性包装方法 https://stackoverflow.com/questions/2206554/c-sharp-wrap-method-via-attributes

我想实现这样的功能:

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

Where [Atomic]attribute 是一个属性,它将函数逻辑包装在事务范围内:

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

这样的属性怎么写呢?

我之前问过 基本一样question https://stackoverflow.com/questions/14294977/attribute-which-wraps-functionality-of-its-decorated-function-within-some-outer,我知道这可以使用 AOP 来完成,但我没有提到我正在寻找一些最简单的概念实现证明或有用的文章,它们可以帮助我使用纯 .NET Framework 编写此内容(我想使用RealProxy and MarshalByRefObject类型,我已经阅读过浏览相关问题)。

我需要准确地解决这个例子。这似乎是一个基本的事情,所以我想从头开始学习如何做。目前不需要安全和灵活。


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

这是(许多)概念很容易理解,但实现起来却一点也不简单的事情之一。

As per 奥德的回答 https://stackoverflow.com/a/14307335/234, .NET 中的属性则不然做任何事情。它们的存在只是为了让其他代码(或开发人员)稍后可以查看它们。将其视为一个奇特的评论。

考虑到这一点,你可以这样写你的属性

public class AtomicAttribute : Attribute { } 

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

鉴于 C# 是一种编译语言,并且考虑到 .NET CLR 的规则,理论上有 3 种方法可以实现此目的

  1. 挂钩 C# 编译器,并使其在看到该属性时输出不同的代码。
    这看起来似乎很好,但这根本不可能 现在。或许是Roslyn http://msdn.microsoft.com/en-us/vstudio/roslyn.aspx项目将来可能允许这样做,但现在你还不能这样做。

  2. 编写一些扫描 .NET 程序集的内容afterC# 编译器已将其转换为 MSIL,并更改 MSIL。
    基本上就是这样后锐利 http://www.sharpcrafters.com/postsharp/features做。扫描并重写MSIL是hard。有一些图书馆,例如莫诺·塞西尔 http://www.mono-project.com/Cecil这会有所帮助,但这仍然是一个非常困难的问题。它还可能会干扰调试器等。

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

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

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

对此的奇特计算机科学术语是高阶编程 http://en.wikipedia.org/wiki/Higher-order_programming

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用标准 .NET Framework 的 AOP 类属性的基本实现 [重复] 的相关文章

  • 静态成员函数与C语言绑定?

    以下 C 代码可使用 Visual C 和 g 进行编译 struct S static void foo extern C void S foo struct T static void foo extern C void T foo a
  • .NET ListView列顺序问题

    我在表单中遇到问题 我已按以下顺序将列添加到 NET ListView 控件 A B C D A D 列的显示索引按顺序为 0 3 但它们的显示顺序错误 A B D C these are switched at runtime 注意 一切
  • ZedGraph 缩放和调整大小

    当我绘制图形 放大和缩小并重新绘制图形时 图形的位置不会改变 我想要做的是 每当重新绘制数据时 视图都会更改以查看所有图形数据 如果您在重绘之前放大或缩小 这似乎会被禁用 Thanks 设置属性 IsZoomOnMouseCenter对于控
  • 具有长期运行对象上下文的实体框架

    我对 WinForms 我敢说 WPF 中的 Linq to SQL 的主要烦恼之一是缺乏对长时间运行的数据上下文的支持 请参阅here http blogs msdn com dinesh kulkarni archive 2008 04
  • ObservableCollection 上的“Cascade”绑定,包含其他 ObservableCollection

    我有一个项目需要显示合同列表 Class Affaire 每个合约都有一个阶段列表 类别阶段 我使用绑定在 2 个不同的 ListView 中显示它们中的每一个 问题是当我从 ListView 中删除一个 Phase 时 显示 Phases
  • 按位非运算符

    为什么要按位运算 0 打印 1 在二进制中 不是0应该是1 为什么 你实际上很接近 在二进制中 不是0应该是1 是的 当我们谈论一位时 这是绝对正确的 然而 一个int其值为0的实际上是32位全零 将所有 32 个 0 反转为 32 个 1
  • .NET 中 IEqualityComparer 中 GetHashCode 的作用是什么?

    我试图了解 IEqualityComparer 接口的 GetHashCode 方法的作用 下面的例子取自MSDN using System using System Collections Generic class Example st
  • 编译器在函数名称前添加下划线前缀的原因是什么?

    当我看到 C 应用程序的汇编代码时 如下所示 emacs hello c clang S O hello c o hello s cat hello s 函数名称以下划线作为前缀 例如callq printf 为什么这样做以及它有什么优点
  • 最小对的总和

    Given 2N点 in a 2D plane 你必须将它们分组为N pairs使得所有对的点之间的距离的总和是最小可能值 所需的输出只是总和 换句话说 如果a1 a2 an分别是第一对 第二对 和第 n 对点之间的距离 则 a1 a2 a
  • 使用 for 循环创建链表

    这是我的结构 struct ListItem int data struct ListItem next 假设链表的第一个节点的 data 0 我想编写一个 for 循环来创建大小为 5 的链表 但我不知道如何工作 我尝试了以下方法 int
  • 复杂的 C 声明

    我刚刚在互联网上浏览了一些代码 发现了这个 float foo SIZE SIZE 我如何阅读这份声明 是否有一套特定的规则来阅读如此复杂的声明 我有一段时间没做这个了 从 开始foo然后向右走 float foo SIZE SIZE fo
  • 一些涉及类析构函数和删除运算符的内存管理问题?

    在阅读了一些教程后 我仍然不清楚 C 中内存管理的一些观点 1 当使用 new 运算符声明的类超出范围时 是否会调用其析构函数并释放内存 是否有必要调用删除运算符来释放类的内存并调用其析构函数 class Test void newTest
  • DLL 中的 XP 风格组合框

    我需要使用 C 和 WIN32 API 无 MFC 在 DLL 中创建 XP 风格的组合框 我设法在 DLL 中创建控件 不是以 XP 风格 我设法在带有清单的 exe 中创建 XP 样式组合框 但它在 DLL 中不起作用 为了让您的 DL
  • 一个对大文件有效的轻量级 XML 解析器?

    我需要解析潜在的巨大 XML 文件 所以我猜这排除了 DOM 解析器 是否有任何优秀的 C 轻量级 SAX 解析器 在占用空间上可与 TinyXML 相媲美 XML的结构非常简单 不需要诸如命名空间和DTD之类的高级东西 只是元素 属性和
  • MPI_Gatherv:根数组中收到的垃圾值

    我正在尝试实施MPI Gatherv函数于C 根据我的程序 包括 root 在内的每个进程都应该创建一个大小等于 进程的等级 1 这将在所有单元格中保持进程的等级 然后这个本地数组被收集到根的 rcv array 中 不知何故 我得到了垃圾
  • Global.asax 错误处理程序或自定义 IHttpModule 错误处理程序未捕获未处理的异常

    我有一个类 DPCal EventMove 的一种方法 我想限制使用角色的访问 我有一个 Global asax cs 错误处理程序和一个自定义 IHttpModule 错误处理程序 旨在捕获未处理的异常 并将它们 Server Trans
  • Azure Function App Azure 服务总线触发器触发两次

    我使用带有服务总线触发器的 Azure Function Apps 来读取服务总线并对服务总线消息的内容执行操作 服务总线接收 JSON 序列化对象 然后将 JSON 消息反序列化回 Function App 中的对象 然而 由于某种原因
  • 即使对于新上下文,OnModelCreating 也仅调用一次

    我有多个相同但内容不同的 SQL Server 表 在编写代码优先 EF6 程序时 我尝试为每个程序重用相同的数据库上下文 并将表名称传递给上下文构造函数 然而 虽然每次都会调用构造函数 但尽管每次都是从 new 创建数据库上下文 但 On
  • 通过 OCI 调用 Oracle 存储过程并使用 C++ 中的 out ref 游标返回结果

    我想使用 OCI 接口从 C 调用 Oracle 存储过程 并使用 out SYS REF CURSOR 作为过程的参数来迭代结果 我是 OCI 新手 所以可能会遗漏一些简单的东西 大部分代码取自这里 我的存储过程是 CREATE OR R
  • Selenium WebDriver 在按钮单击事件上无法正常工作。这里有什么问题呢?

    I am using following code to scrape data from a website I have following interface 这是 HTML div class es content div

随机推荐