| 1 2 3 4 | publicstaticstringGetPoint(intx, inty) {    varvalue=x;} | 
哇 好简单啊。其实动态获取和我们普通这样写代码是一样的,我们把要注入的代码,生成一个接收的变量就可以了。
就像上面value 一样接收,然后传递给我们自己函数就可以了。
  public class WeaveService : Attribute
    {
    }
    public class WeaveAction : Attribute
    {
    }
    public class Log : WeaveAction
    {
        public static void OnActionBefore(MethodBase mbBase, object[] args)
        {
            for (int i = 0; i < args.Length; i++)
            {
                Console.WriteLine(string.Format("{0}方法,第{1}参数是:{2}",mbBase.Name,i, args[i]));
            }
        }
    }
WeaveService WeaveAction 2个Attribute是注入的标记,方便我们在注入查找快速定位。
OnActionBefore是我们的接收函数,arg就是函数运行时的参数。
这块代码在上一篇已经有详细注释了,这里不多描述。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | publicstaticvoidWeave(string[] assemblyPath)       {           foreach(varitem inassemblyPath)           {               varassembly = AssemblyDefinition.ReadAssembly(item);               vartypes = assembly.MainModule.Types.Where(n => n.CustomAttributes.Any(y => y.AttributeType.Resolve().Name == "WeaveService"));               foreach(vartype intypes)               {                   foreach(varmethod intype.Methods)                   {                       varattrs =                           method.CustomAttributes.Where(y => y.AttributeType.Resolve().BaseType.Name == "WeaveAction");                       foreach(varattr inattrs)                       {                           varresolve = attr.AttributeType.Resolve();                           varilProcessor = method.Body.GetILProcessor();                           varfirstInstruction = ilProcessor.Body.Instructions.First();                           varonActionBefore = resolve.GetMethods().Single(n => n.Name == "OnActionBefore");                           varmfReference = assembly.MainModule.Import(typeof(System.Reflection.MethodBase).GetMethod("GetCurrentMethod"));                           ilProcessor.InsertBefore(firstInstruction, ilProcessor.Create(OpCodes.Call, mfReference));                           MakeArrayOfArguments(method, firstInstruction, ilProcessor, 0, method.Parameters.Count, assembly);                           ilProcessor.InsertBefore(firstInstruction, ilProcessor.Create(OpCodes.Call, onActionBefore));                       }                   }               }               if(types.Any())               {                   assembly.Write(item);               }           }       } | 
动态获取函数参数的函数,代码有详细注释。
 1    /// <summary>
 2         /// 构建函数参数
 3         /// </summary>
 4         /// <param name="method">要注入的方法</param>
 5         /// <param name="firstInstruction">函数体内第一行指令认 IL_0000: nop</param>
 6         /// <param name="writer">mono IL处理容器</param>
 7         /// <param name="firstArgument">默认第0个参数开始</param>
 8         /// <param name="argumentCount">函数参数的数量,静态数据可以拿到</param>
 9         /// <param name="assembly">要注入的程序集</param>
10         public static void MakeArrayOfArguments(MethodDefinition method, Instruction firstInstruction, ILProcessor writer, int firstArgument,
11                                           int argumentCount, AssemblyDefinition assembly)
12         {
13             //实例函数第一个参数值为this(当前实例对象),所以要从1开始。
14             int thisShift = method.IsStatic ? 0 : 1;
15 
16             if (argumentCount > 0) 
17             {
18                 //我们先创建个和原函数参数,等长的空数组。
19                 writer.InsertBefore(firstInstruction, writer.Create(OpCodes.Ldc_I4, argumentCount - firstArgument));
20                 //然后实例object数组,赋值给我们创建的数组
21                 writer.InsertBefore(firstInstruction, writer.Create(OpCodes.Newarr,
22                                             assembly.MainModule.Import(typeof(object))));
23 
24                 //c#代码描述
25                 //object[] arr=new object[argumentCount - firstArgument] 
26                 for (int i = firstArgument; i < argumentCount; i++)  //遍历参数
27                 {
28                     var parameter = method.Parameters[i];
29 
30                     //在堆栈上复制一个值
31                     writer.InsertBefore(firstInstruction, writer.Create(OpCodes.Dup));
32                     //将常量 i - firstArgument 进行压栈,数组[i - firstArgument] 这个东东。
33                     writer.InsertBefore(firstInstruction, writer.Create(OpCodes.Ldc_I4, i - firstArgument));
34                     //将第i + thisShift个参数 压栈。  
35                     writer.InsertBefore(firstInstruction, writer.Create(OpCodes.Ldarg, (short)(i + thisShift)));
36                     //装箱成object
37                     ToObject(assembly, firstInstruction, parameter.ParameterType, writer);
38                     //压栈给数组 arr[i]赋值
39                     writer.InsertBefore(firstInstruction, writer.Create(OpCodes.Stelem_Ref));
40 
41                     //c#代码描述
42                     // arr[i]=value;
43                 }
44             }
45             else
46             {
47                 writer.InsertBefore(firstInstruction, writer.Create(OpCodes.Ldnull));
48             }
49         }
50         public static void ToObject(AssemblyDefinition assembly, Instruction firstInstruction, TypeReference originalType, ILProcessor writer)
51         {
52             if (originalType.IsValueType)
53             {
54                 //普通值类型进行装箱操作
55                 writer.InsertBefore(firstInstruction, writer.Create(OpCodes.Box, originalType));
56             }
57             else
58             {
59                 if (originalType.IsGenericParameter)
60                 {
61                     //集合装箱
62                     writer.InsertBefore(firstInstruction, writer.Create(OpCodes.Box, assembly.MainModule.Import(originalType)));
63                 }
64 
65             }
66         }
介绍下mono InsertBefore这个函数。 这个函数是在某个指令之前插入指令。来张图

通过图我们看出,第一行指令是IL_0000: nop 。 第一行追加了 ldc.i4 2 指令,第二行我们还是nop 之前追加。 自上而下
我定义个要注入的用户类,然后标记下。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | [WeaveService]  publicstaticclassUserManager  {      [Log]      publicstaticstringGetUserName(intuserId, stringmemberid)      {          return"成功";      }      [Log]      publicstaticstringGetPoint(intx, inty)      {          varsum = x + y;          return"用户积分: "+ sum;      }  } | 
我们平常的业务写法,不需要多余操作。
| 1 2 3 4 5 6 7 8 9 | publicstaticvoidMain(string[] args)       {                    UserManager.GetUserName(1,"v123465");               UserManager.GetPoint(2, 3);           Console.ReadLine();       } | 
我把业务类编译输入到D盘,用我们前面的Weave函数进行注入。
  CodeInject.Weave(new string[] { @"D:\test\Test.exe" });
运行结果如下

反编译后的c#

通过静态注入,我们能更好的从用途上去了解IL语言。
拿到动态数据仅仅抛砖引玉。 利用Mono我们可以写自己的AOP静态组件。
1:postsharp源码
2:http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes_fields(v=vs.110).aspx
使用Mono Cecil 动态获取运行时数据 (Atribute形式 进行注入) -摘自网络
原文:http://www.cnblogs.com/haoliansheng/p/4349074.html