Giter Site home page Giter Site logo

csil's Introduction

CSIL

使用 IL weaving 在运行时拦截C#方法调用, 实现拦截器的功能.

            public class MyClass : IMyInterface
            {
                public string MyMethod(string foo, int bar)
                {
                    Console.WriteLine($"Executing MyMethod in MyClass, {foo}, {bar}");
                    return "123";
                }
            }

            public class MyInterceptor : IInterceptor
            {
                public void BeforeInvoke()
                {
                    Console.WriteLine("Before invoking method");
                }
        
                public void AfterInvoke()
                {
                    Console.WriteLine("After invoking method");
                }
            }

            // 创建目标对象实例
            IMyInterface target = new MyClass();

            // 创建拦截器实例
            IInterceptor interceptor = new MyInterceptor();

            // 创建动态代理对象
            IMyInterface proxy = MyProxyGenerator.CreateInterfaceProxyWithTarget(target, interceptor);

            // 调用代理对象的方法
            var ret = proxy.MyMethod("aaa", 1234);
            Console.WriteLine(ret);

Output:

Before invoking method
Executing MyMethod in MyClass, aaa, 1234
After invoking method
123

IL Weaving

动态生成代理类, 劫持原方法. 生成与原类实现相同接口的代理类, 覆盖所有方法为携带原调用的methodInfo, thisparams 调用劫持方法 InvokeMethod(MethodInfo method, object proxy, object[] args)

覆盖的方法:

  • 加载methodInfo入栈
  • 将第一个参数(this)压栈
  • 创建object[]数组arr用于存储原参数列表
  • 循环将原参数压入arr, 引用类型直接存入引用, 值类型装箱然后存入
  • 调用劫持方法InvokeMethod (在此方法内调用Interceptor代码, 然后调用原方法)
  • InvokeMethod 返回原方法返回值到栈顶
  • 返回返回值.
                il = methodBuilder.GetILGenerator();
                // load methodInfo
                il.Emit(OpCodes.Ldtoken, methodInfo);
                il.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetMethodFromHandle", new Type[] { typeof(RuntimeMethodHandle) }));
                il.Emit(OpCodes.Castclass, typeof(MethodInfo));
                // load this
                il.Emit(OpCodes.Ldarg_0);
                // create object[] for arguments
                LocalBuilder arr = il.DeclareLocal(typeof(object[]));
                int nargs = methodInfo.GetParameters().Length;
                il.Emit(OpCodes.Ldc_I4, nargs); // 将参数个数推入栈顶
                il.Emit(OpCodes.Newarr, typeof(object)); // 创建一个 object[] 数组
                il.Emit(OpCodes.Stloc, arr); // 将数组引用存储到本地变量 argsArray 中
                for (int i = 0; i < nargs; i++)
                {
                    // 将数组引用加载到栈顶
                    il.Emit(OpCodes.Ldloc, arr);
                    // 将数组索引推入栈顶
                    il.Emit(OpCodes.Ldc_I4, i);
                    // 将参数值加载到栈顶
                    ParameterInfo paramInfo = methodInfo.GetParameters()[i];
                    Type paramType = paramInfo.ParameterType;
                    if (paramType.IsValueType) //如果是数值类型, 装箱
                    {
                        il.Emit(OpCodes.Ldarg, i + 1); // 加载参数值到栈顶
                        il.Emit(OpCodes.Box, paramType); // 执行装箱操作
                    }
                    else
                    {
                        // 对于引用类型参数,直接加载参数值到栈顶
                        il.Emit(OpCodes.Ldarg, i + 1);
                    }
                    il.Emit(OpCodes.Stelem_Ref);
                }

                il.Emit(OpCodes.Ldloc, arr);
                il.Emit(OpCodes.Call, typeof(MyProxyGenerator)
                    .GetMethod(nameof(InvokeMethod), BindingFlags.Public | BindingFlags.Static));
                 
                il.Emit(OpCodes.Ret);
            }

csil's People

Contributors

bkmashiro avatar

Stargazers

FUNction avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.