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

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

问题描述

  

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

我想实现这样的功能:

  [原子]
公共无效美孚()
{
    / * foo的逻辑* /
}
 

其中, [原子] 属性是一个属性,它包装在一个事务中功能逻辑:

 使用(VAR范围=新的TransactionScope())
{
    / * foo的逻辑* /
    scope.Complete();
}
 

如何写出这样的属性?

我已经问过,基本上是相同的<一个href="http://stackoverflow.com/questions/14294977/attribute-which-wraps-functionality-of-its-decorated-function-within-some-outer">question,我知道这是可以做到使用AOP,但我没有提到我在寻找一些简单的概念,实施或帮助信息的证明,可以帮我写这个使用纯.NET框架(我估计使用 RealProxy MarshalByRefObject的类型,对此我读过浏览相关的问题)。

我需要解决的正是这种显示的例子。这似乎是一个基本的东西,所以我想学习如何做到这一点从头开始。它并不需要是安全的,灵活的,现在

解决方案
  

这似乎是一个基本的东西...

这是的(多)东西是很容易理解的概念之一,但不是在所有容易实现。

根据奥德的回答,属性在.NET中没有的做任何事情的。它们只存在让其他code(或开发商)可以看他们以后。把它看成是一个奇特的注释。

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

 公共类AtomicAttribute:属性{}
 

现在最困难的部分,你必须写一些code扫描该属性,并更改code的行为。

由于C#的编译语言,并给出了.NET CLR的规则也有理论上的3种方法可以做到这一点。

  1. 勾成C#编译器,使当它看到该属性是不同的输出code。
    这似乎是这将是很好的,但它根本不可能 现在。也许 罗斯林 项目可能会允许这样的未来,但现在,你不能做到这一点。

  2. 写的东西之后,将扫描的.NET程序集的 的C#编译器已经将其转换为MSIL,并更改MSIL。
    这基本上是 PostSharp 一样。扫描和重写MSIL是的硬盘的。还有如 Mono.Cecil能做到库,它可以帮助,但它仍然是一个非常棘手的问题。它也可能会干扰与调试器等

  3. 使用的.NET分析API的在运行监视程序,你可以看到与该属性的函数调用每次重定向到其他一些包装函数。
    这也许是最简单的选择(虽然它仍然的非常困难的),但缺点是,你的程序现在的必须的探查下运行。这可能是罚款的开发PC上,但如果您尝试部署它就会造成一个巨大的问题。此外,还有可能是使用这种方法的大的性能损失。

在我看来,最好的办法是创建一个包装函数,它设置了交易,然后把它传递一个lambda来完成实际的工作。像这样的:

 公共静态类内线
{
    公共静态无效原子(动作的动作)
    {
        使用(VAR范围=新的TransactionScope())
        {
            行动();
            scope.Commit();
        }
    }
}


公共无效美孚()
{
    Ext.Atomic(()=&GT; {
        // foo的逻辑
    }
}
 

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

Possible Duplicate:
C# wrap method via attributes

I'd like to achieve such functionality:

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

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

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

How to write such an attribute?

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.

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.

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

  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.

  2. 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.

  3. 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.

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();
        }
    }
}


public void Foo()
{
    Ext.Atomic(() => {
        // foo logic
    }
}

The fancy computer science term for this is Higher order programming

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

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