如何知道我的应用程序代码中何时调用了任何方法? [英] How to know when any method is called in my application code?

查看:28
本文介绍了如何知道我的应用程序代码中何时调用了任何方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只是为了好玩,我想写一个方面,比如日志记录、跟踪或检测/分析.但我不想使用任何已经可用的 AOP 框架.

Just for fun, I want to write an aspect such as say logging, tracing or instrumentation/profiling. But I don't want to use any of the available AOP frameworks already available.

我过去用过 PostSharp,现在 ASP.NET MVC 引入了动作过滤器,它与方面/建议注入非常相似,而 .NET 4 有 CodeContracts,它也与方面非常相似,我有一个非常清楚我希望方面 API 的样子.

I've used PostSharp in the past and now that ASP.NET MVC introduces action filters, which are very similar to aspect/advise injection, and .NET 4 has CodeContracts, which are also very similar to aspects, I have a pretty good idea of what I want my aspect API to look like.

我唯一还没有弄清楚的事情,我相信构建 AOP 库的核心是如何知道一个方法何时被调用?

The only thing I haven't figured out yet, and I believe that it is central to building an AOP library, is how to know when a method is being invoked?

什么,我一直在看调用堆栈吗?我是否查找主 UI 线程及其同步上下文以查看它是否被分配了一些工作,即是否被赋予了进入的方法?有什么方法可以知道某个方法是否会被调用?

What, do I keep watching the callstack? Do I look up the main UI thread and its synchronization context to see if it has been assigned some work, i.e. been given a method to enter into? What is the way to know if a method is going to be called?

推荐答案

有两种方法可以知道某个方法是否将被调用.

There are two ways to know if a method is going to be called.

  1. 你可以从 ContextBoundObject 继承,但是你失去了基类的唯一机会.您可以查看这个

您可以继承您的类并覆盖您的方法.新方法可以在调用基方法之前调用拦截器.幸运的是,这个派生类可以在运行时构造.实际上,这就是 Castle 的 DynamicProxy 所做的.详细地,您构建一个继承您的类的类型,以便在运行时拦截并实例化这个派生类.您将 IL 代码发送到新生成的类的方法中.

You can inherit your class and override your methods. New methods can call a interceptor before calling base method. Fortunately, this derived class can be constructed in run time. Actually, this is what Castle's DynamicProxy does. In detail you build a type that inherits your class to be intercepted in run time and instantiate this derived class. You Emit IL code into methods of newly generated class.

我不知道是否允许粘贴长代码,但这是我编写的一个小版本的 DynamicProxy.它唯一依赖的库是System.你可以这样使用它.

I do not know if pasting long codes are allowed but here is a little version of DynamicProxy that I wrote. The only library it depends on is System. You can use it like this.

// typeof obj: public class TestClassProxy : TestClass, IInterface1, IIterface2
var obj = Proxy.Of<TestClass>(new CallHandler(), typeof(IInterface1), typeof(IInterface2));

obj.MethodVoid();
Console.WriteLine(obj.PublicSquare(3));
Console.WriteLine(obj.MethodString());

触发处理程序方法:

  1. 在调用方法之前(BeforeMethodCall)
  2. 调用方法后(AfterMethodCall)
  3. 如果方法(OnError)中发生异常

所有这些方法都接受参数、拥有该方法的对象、当前方法的MethodInfo和传递给方法的参数.另外 AfterMethodCall 接受返回值,OnError 接受抛出的异常.

All these methods accepts the parameters, object that has the method, MethodInfo of the current method and aguments passed to method. Addtionally AfterMethodCall takes return value and OnError takes the exception that has thrown.

这是神奇的Proxy

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;

namespace emit
{
public class Proxy
{
    #region static

    private static readonly AssemblyBuilder AssemblyBuilder;
    private static readonly ModuleBuilder ModuleBuilder;

    private static readonly object LockObj = new Object();
    private static readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();

    static Proxy()
    {
        lock (LockObj)
        {
            AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
                new AssemblyName("Taga.Proxies"),
                AssemblyBuilderAccess.Run);

            var assemblyName = AssemblyBuilder.GetName().Name;

            ModuleBuilder = AssemblyBuilder.DefineDynamicModule(assemblyName);
        }
    }

    private static Type GetImplementedType(Type baseType, Type[] interfaceTypes)
    {
        var key = GetTypeKey(baseType, interfaceTypes);
        return TypeCache.ContainsKey(key) ? TypeCache[key] : null;
    }

    private static void AddImplementation(Type baseType, Type[] interfaceTypes, Type implementationType)
    {
        var key = GetTypeKey(baseType, interfaceTypes);
        TypeCache.Add(key, implementationType);
    }

    private static string GetTypeKey(Type baseType, Type[] interfaceTypes)
    {
        var key = String.Empty;
        key += baseType.FullName;
        key = interfaceTypes.Aggregate(key, (current, interfaceType) => current + interfaceType);
        return key;
    }

    public static TBase Of<TBase>(ICallHandler callHandler, params Type[] interfaceTypes) where TBase : class
    {
        var builder = new Proxy(typeof(TBase), interfaceTypes);
        var type = builder.GetProxyType();
        return (TBase)Activator.CreateInstance(type, callHandler);
    }

    public static object Of(ICallHandler callHandler, Type[] interfaceTypes)
    {
        if (interfaceTypes == null || interfaceTypes.Length == 0)
            throw new InvalidOperationException("No interface type specified");
        return Of<object>(callHandler, interfaceTypes);
    }

    #endregion

    #region Proxy

    private TypeBuilder _typeBuilder;
    private FieldBuilder _callHandlerFieldBuilder;
    private readonly Type _baseClassType;
    private readonly Type[] _interfaceTypes;

    private Proxy(Type baseClassType, Type[] interfaceTypes)
    {
        if (interfaceTypes == null || !interfaceTypes.Any())
            _interfaceTypes = Type.EmptyTypes;
        else if (interfaceTypes.Any(it => !it.IsInterface || !it.IsPublic || it.IsGenericType))
            throw new InvalidOperationException("Interface Types must be public and non generic");
        else
            _interfaceTypes = interfaceTypes;

        if (baseClassType == null)
            _baseClassType = typeof(object);
        else if (!baseClassType.IsClass || baseClassType.IsAbstract || baseClassType.IsGenericType || baseClassType.IsSealed || !baseClassType.IsPublic || !baseClassType.HasDefaultConstructor())
            throw new InvalidOperationException("Base Class Type must be a public, non-sealed, non-abstract, non-generic class with a public default constructor");
        else
            _baseClassType = baseClassType;
    }

    private string _typeName;
    private string TypeName
    {
        get { return _typeName ?? (_typeName = BuildTypeName()); }
    }

    private string BuildTypeName()
    {
        var typeName = "__";

        if (_baseClassType != null)
            typeName += _baseClassType.Name + "__";

        foreach (var interfaceType in _interfaceTypes)
            typeName += interfaceType.Name + "__";

        return typeName + "Proxy__";
    }

    private Type GetProxyType()
    {
        var type = GetImplementedType(_baseClassType, _interfaceTypes);
        if (type != null)
            return type;

        type = BuildType();

        AddImplementation(_baseClassType, _interfaceTypes, type);
        return type;
    }

    private Type BuildType()
    {
        InitTypeBuilder();
        DefineCallHandlerField();
        BuildConstructor();
        ExtendBase();
        ImplementInterfaces();

        return _typeBuilder.CreateType();
    }

    private void InitTypeBuilder()
    {
        // public class __BaseClass__Interface1__Interface2__Proxy__ : BaseClass, Interface1, Interface2
        _typeBuilder = ModuleBuilder.DefineType(
            TypeName,
            TypeAttributes.Public | TypeAttributes.Class,
            _baseClassType,
            _interfaceTypes);
    }

    private void DefineCallHandlerField()
    {
        // private ICallHandler _callHandler;
        _callHandlerFieldBuilder = _typeBuilder.DefineField("_callHandler", typeof(ICallHandler), FieldAttributes.Private);
    }

    private void BuildConstructor()
    {
        var constructorBuilder = DeclareContsructor();   // public ProxyClass(ICallHandler callHandler)
        ImplementConstructor(constructorBuilder);       // : base() { this._callHandler = callHandler; }
    }

    private void ExtendBase()
    {
        foreach (var mi in _baseClassType.GetVirtualMethods())
            BuildMethod(mi);
    }

    private void ImplementInterfaces()
    {
        foreach (var methodInfo in _interfaceTypes.SelectMany(interfaceType => interfaceType.GetMethods()))
            BuildMethod(methodInfo);
    }

    private ConstructorBuilder DeclareContsructor()
    {
        var constructorBuilder = _typeBuilder.DefineConstructor(
            MethodAttributes.Public,
            CallingConventions.HasThis,
            new[] { typeof(ICallHandler) });
        return constructorBuilder;
    }

    private void ImplementConstructor(ConstructorBuilder constructorBuilder)
    {
        var baseCtor = _baseClassType.GetConstructor(Type.EmptyTypes);

        var il = constructorBuilder.GetILGenerator();

        // call base ctor
        il.Emit(OpCodes.Ldarg_0); // push this
        il.Emit(OpCodes.Call, baseCtor); // Call base constructor this.base(); pops this

        // set _callHandler
        il.Emit(OpCodes.Ldarg_0); // push this
        il.Emit(OpCodes.Ldarg_1); // push callHandler argument
        il.Emit(OpCodes.Stfld, _callHandlerFieldBuilder); // this._callHandler = callHandler, pop this, pop callhandler argument

        il.Emit(OpCodes.Ret); // exit ctor
    }

    private void BuildMethod(MethodInfo mi)
    {
        var methodBuilder = CallHandlerMethodBuilder.GetInstance(_typeBuilder, mi, _callHandlerFieldBuilder);
        methodBuilder.Build();
    }

    #endregion
}

class CallHandlerMethodImplementor : CallHandlerMethodBuilder
{
    internal CallHandlerMethodImplementor(TypeBuilder typeBuilder, MethodInfo methodInfo, FieldBuilder callHandlerFieldBuilder)
        : base(typeBuilder, methodInfo, callHandlerFieldBuilder)
    {
    }

    protected override void SetReturnValue()
    {
        // object res = returnValue;
        ReturnValue = IL.DeclareLocal(typeof(object));
        if (MethodInfo.ReturnType != typeof(void))
            IL.Emit(OpCodes.Stloc, ReturnValue); // pop return value of BeforeCall into res
        else
            IL.Emit(OpCodes.Pop); // pop return value of BeforeCall
    }
}

class CallHandlerMethodOverrider : CallHandlerMethodBuilder
{
    internal CallHandlerMethodOverrider(TypeBuilder typeBuilder, MethodInfo methodInfo, FieldBuilder callHandlerFieldBuilder)
        : base(typeBuilder, methodInfo, callHandlerFieldBuilder)
    {
    }

    protected override void SetReturnValue()
    {
        // ReturnValue = base.Method(args...)
        CallBaseMethod();
        // stack'ta base'den dönen değer var
        SetReturnValueFromBase();
    }

    private void CallBaseMethod()
    {
        IL.Emit(OpCodes.Pop); // pop return value of BeforeCall

        // base'den Method'u çağır
        // returnValue = base.Method(params...)
        IL.Emit(OpCodes.Ldarg_0); // push this 
        for (var i = 0; i < ParameterCount; i++)  // metoda gelen parametreleri stack'e at
            IL.Emit(OpCodes.Ldarg_S, i + 1);// push params[i]
        IL.Emit(OpCodes.Call, MethodInfo); // base.Method(params) pop this, pop params push return value
    }

    private void SetReturnValueFromBase()
    {
        ReturnValue = IL.DeclareLocal(typeof(object));

        if (MethodInfo.ReturnType == typeof(void))
            return;

        // unbox returnValue if required
        if (MethodInfo.ReturnType.IsValueType)
            IL.Emit(OpCodes.Box, MethodInfo.ReturnType);
        IL.Emit(OpCodes.Stloc, ReturnValue); // pop return value into res
    }
}

abstract class CallHandlerMethodBuilder
{
    private ParameterInfo[] _parameters;
    private MethodBuilder _methodBuilder;
    private readonly TypeBuilder _typeBuilder;
    private readonly FieldBuilder _callHandlerFieldBuilder;

    protected readonly MethodInfo MethodInfo;

    protected ILGenerator IL { get; private set; }
    protected int ParameterCount { get; private set; }

    private MethodInfo _beforeCall;
    private MethodInfo BeforeCall
    {
        get
        {
            return _beforeCall ?? (_beforeCall = typeof(ICallHandler).GetMethods().First(m => m.Name == "BeforeMethodCall"));
        }
    }

    private MethodInfo _afterCall;
    private MethodInfo AfterCall
    {
        get
        {
            return _afterCall ?? (_afterCall = typeof(ICallHandler).GetMethods().First(m => m.Name == "AfterMethodCall"));
        }
    }

    private MethodInfo _onError;
    private MethodInfo OnError
    {
        get
        {
            return _onError ?? (_onError = typeof(ICallHandler).GetMethods().First(m => m.Name == "OnError"));
        }
    }

    protected CallHandlerMethodBuilder(TypeBuilder typeBuilder, MethodInfo methodInfo, FieldBuilder callHandlerFieldBuilder)
    {
        _typeBuilder = typeBuilder;
        MethodInfo = methodInfo;
        _callHandlerFieldBuilder = callHandlerFieldBuilder;
    }

    private void Declare()
    {
        // public override? ReturnType Method(arguments...)
        _methodBuilder = _typeBuilder.DefineMethod(MethodInfo.Name,
                                                      MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual,
                                                      MethodInfo.ReturnType,
                                                      MethodInfo.GetParameterTypes());
        IL = _methodBuilder.GetILGenerator();

        _parameters = MethodInfo.GetParameters();
        ParameterCount = _parameters.Length;
    }

    private LocalBuilder _objParameter;
    private void SetObjectParameter()
    {
        // CallHandlera verilecek object obj
        _objParameter = IL.DeclareLocal(typeof(object)); // object obj;
        IL.Emit(OpCodes.Ldarg_0); // push this
        IL.Emit(OpCodes.Stloc, _objParameter); // obj = this; pops this
    }

    private LocalBuilder _methodInfoParameter;
    private void SetMethodInfoParameter()
    {
        // CallHandlera verilecek MethodInfo methodInfo
        _methodInfoParameter = IL.DeclareLocal(typeof(MethodInfo)); // MethodInfo methodInfo;
        IL.Emit(OpCodes.Ldtoken, MethodInfo);
        IL.Emit(OpCodes.Call, typeof(MethodBase).GetMethod(
            "GetMethodFromHandle", new[] { typeof(RuntimeMethodHandle) })); // MethodBase.GetMethodFromHandle(new RuntimeMethodHandle());
        IL.Emit(OpCodes.Stloc, _methodInfoParameter);
    }

    private LocalBuilder _argsParameter;
    private void SetArgsParameters()
    {
        // CallHandlera verilecek object[] args
        _argsParameter = IL.DeclareLocal(typeof(object[])); // object[] args;
        IL.Emit(OpCodes.Ldc_I4, ParameterCount); // push parameterCount as Int32
        IL.Emit(OpCodes.Newarr, typeof(object)); // push new object[parameterCount]; pops parameterCount
        IL.Emit(OpCodes.Stloc, _argsParameter); // args = new object[ParameterCount]; pops new object[parameterCount]

        // Metoda gelen parametreleri args'a doldur
        for (var i = 0; i < ParameterCount; i++)
        {
            var parameterInfo = _parameters[i];

            IL.Emit(OpCodes.Ldloc, _argsParameter); // push args
            IL.Emit(OpCodes.Ldc_I4, i); // push i
            IL.Emit(OpCodes.Ldarg_S, i + 1); // push params[i]; pops i; metoda gelen parametrelerin i'incisi. 0'ıncı parametre this olduğu için  "+1" var
            if (parameterInfo.ParameterType.IsPrimitive || parameterInfo.ParameterType.IsValueType)
                IL.Emit(OpCodes.Box, parameterInfo.ParameterType); // (object)params[i]
            IL.Emit(OpCodes.Stelem_Ref); // args[i] = (object)params[i]; pops params[i]
        }
    }

    private void Try()
    {
        IL.BeginExceptionBlock(); // try {
    }

    private void InvokeBeforeMethodCall()
    {
        // this._callHandler.BeforeCall(obj, methodInfo, args);
        IL.Emit(OpCodes.Ldarg_0); // push this
        IL.Emit(OpCodes.Ldfld, _callHandlerFieldBuilder); // push _callHandler; pops this
        IL.Emit(OpCodes.Ldloc, _objParameter); // push obj
        IL.Emit(OpCodes.Ldloc, _methodInfoParameter); // push methodInfo 
        IL.Emit(OpCodes.Ldloc, _argsParameter); // push args
        IL.Emit(OpCodes.Call, BeforeCall); // _callHandler.BeforeCall(obj, methodInfo, args); push return value
    }

    protected LocalBuilder ReturnValue;
    protected abstract void SetReturnValue();

    private void InvokeAfterMethodCall()
    {
        // this._callHandler.AfterCall(obj, methodInfo, args, returnValue);
        IL.Emit(OpCodes.Ldarg_0); // push this
        IL.Emit(OpCodes.Ldfld, _callHandlerFieldBuilder); // push _callHandler; pops this
        IL.Emit(OpCodes.Ldloc, _objParameter); // push obj
        IL.Emit(OpCodes.Ldloc, _methodInfoParameter); // push methodInfo 
        IL.Emit(OpCodes.Ldloc, _argsParameter); // push args
        IL.Emit(OpCodes.Ldloc, ReturnValue); // push res
        IL.Emit(OpCodes.Call, AfterCall); // _callHandler.AfterCall(obj, methodInfo, args, returnValue); push return value (void değilse)
    }

    private void Catch()
    {
        var ex = IL.DeclareLocal(typeof(Exception)); 

        IL.BeginCatchBlock(typeof(Exception));          // catch 
        IL.Emit(OpCodes.Stloc_S, ex);                   // (Exception ex) {
        InvokeOnError(ex);                              //     _callHandler.AfterCall(obj, methodInfo, args);
        IL.EndExceptionBlock();                         // }
    }

    private void InvokeOnError(LocalBuilder exception)
    {
        // this._callHandler.OnError(obj, methodInfo, args);
        IL.Emit(OpCodes.Ldarg_0); // push this
        IL.Emit(OpCodes.Ldfld, _callHandlerFieldBuilder); // push _callHandler; pops this
        IL.Emit(OpCodes.Ldloc, _objParameter); // push obj
        IL.Emit(OpCodes.Ldloc, _methodInfoParameter); // push methodInfo 
        IL.Emit(OpCodes.Ldloc, _argsParameter); // push args
        IL.Emit(OpCodes.Ldloc, exception); // push ex
        IL.Emit(OpCodes.Call, OnError); // _callHandler.AfterCall(obj, methodInfo, args);
    }

    private void Return()
    {
        if (MethodInfo.ReturnType != typeof(void))
        {
            IL.Emit(OpCodes.Ldloc, ReturnValue); // push returnValue
            IL.Emit(OpCodes.Unbox_Any, MethodInfo.ReturnType); // (ReturnType)returnValue
        }

        IL.Emit(OpCodes.Ret); // returns the value on the stack, if ReturnType is void stack should be empty
    }

    internal void Build()
    {
        Declare();                   // public override? ReturnType Method(arguments...) {
        SetObjectParameter();        //     object obj = this;
        SetMethodInfoParameter();    //     MethodInfo methodInfo = MethodBase.GetMethodFromHandle(new RuntimeMethodHandle());
        SetArgsParameters();         //     object[] args = arguments;
        Try();                       //     try {
        InvokeBeforeMethodCall();    //         object returnValue = _callHandler.BeforeMethodCall(obj, methodInfo, args);
        SetReturnValue();            //         !IsAbstract => returnValue = (object)base.Method(arguments);
        InvokeAfterMethodCall();     //         _callHandler.AfterMethodCall(obj, methodInfo, args, returnValue);
        Catch();                     //      } catch (Exception ex) { _callHandler.OnError(obj, methodInfo, args, ex); }
        Return();                    //     IsVoid ? (return;) : return (ReturnType)returnValue; }
    }

    internal static CallHandlerMethodBuilder GetInstance(TypeBuilder typeBuilder, MethodInfo methodInfo, FieldBuilder callHandlerFieldBuilder)
    {
        if (methodInfo.IsAbstract)
            return new CallHandlerMethodImplementor(typeBuilder, methodInfo, callHandlerFieldBuilder);
        return new CallHandlerMethodOverrider(typeBuilder, methodInfo, callHandlerFieldBuilder);
    }
}

public interface ICallHandler
{
    object  BeforeMethodCall    (object obj, MethodInfo mi, object[] args);
    void    AfterMethodCall     (object obj, MethodInfo mi, object[] args, object returnValue);
    void    OnError             (object obj, MethodInfo mi, object[] args, Exception exception);
}

static class ReflectionExtensions
{
    public static bool HasDefaultConstructor(this Type type)
    {
        return type.GetConstructors(BindingFlags.Public | BindingFlags.Instance).Any(ctor => !ctor.GetParameters().Any());
    }

    public static Type[] GetParameterTypes(this MethodInfo methodInfo)
    {
        return methodInfo.GetParameters().Select(pi => pi.ParameterType).ToArray();
    }

    public static MethodBuilder GetMethodBuilder(this TypeBuilder typeBuilder, MethodInfo mi)
    {
        // MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual
        return typeBuilder.DefineMethod(mi.Name, mi.Attributes, mi.ReturnType, mi.GetParameterTypes());
    }

    public static MethodInfo[] GetVirtualMethods(this Type type)
    {
        return type.GetMethods().Where(mi => mi.IsVirtual).ToArray();
    }

    public static object GetDefaultValue(this Type t)
    {
        return typeof(ReflectionExtensions).GetMethod("Default").MakeGenericMethod(t).Invoke(null, null);
    }

    public static T Default<T>()
    {
        return default(T);
    }
}
}

这是测试代码

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Threading;

namespace emit
{
public class Program
{
    private static void Main()
    {
        Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB");
        try
        {
            TestProxy();
            Console.WriteLine("OK");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
        Console.ReadLine();
    }

    private static void TestProxy()
    {
        var obj = Proxy.Of<TestClass>(new CallHandler(), typeof(IInterface1), typeof(IInterface2));

        obj.MethodVoid();
        Console.WriteLine();
        Console.WriteLine(obj.PublicSquare(3));
        Console.WriteLine();
        Console.WriteLine(obj.MethodString());
        Console.WriteLine();
        Console.WriteLine(obj.MethodInt());
        Console.WriteLine();
        Console.WriteLine(obj.MethodComplex(45, " Deneme ", new Ogrenci { Name = "Ali" }).Name);
        Console.WriteLine();
        obj.PropInt = 78;
        Console.WriteLine();
        Console.WriteLine(obj.PropInt);
        Console.WriteLine();

        var int1 = obj as IInterface1;
        int1.Name = "Interface";
        Console.WriteLine();
        Console.WriteLine("Got: " + int1.Name);
        Console.WriteLine();
        int1.Name = "Interface333";
        Console.WriteLine();
        Console.WriteLine("Got3: " + int1.Name);
        Console.WriteLine();
        Console.WriteLine(int1.MethodString(34, "Par", new Ogrenci { Name = "Veli" }));

        var int2 = obj as IInterface2;
        int2.Value = 14;
        Console.WriteLine();
        Console.WriteLine("Got: " + int2.Value);
        Console.WriteLine();
        int2.Value = 333;
        Console.WriteLine();
        Console.WriteLine("Got3: " + int2.Value);
        Console.WriteLine();
        Console.WriteLine(int2.MethodInt(34, "Par", new Ogrenci { Name = "Veli" }));
        Console.WriteLine();

        obj.ThrowException();
    }
}

public class CallHandler : ICallHandler
{
    private readonly SortedDictionary<string, object> _propertyValues = new SortedDictionary<string, object>();

    public object BeforeMethodCall(object obj, MethodInfo mi, object[] args)
    {
        WriteParameterInfo(mi, args);
        return SetReturnValue(mi, args);
    }

    public void AfterMethodCall(object obj, MethodInfo mi, object[] args, object returnValue)
    {
        if (mi.ReturnType == typeof(void))
            Console.WriteLine(mi.Name + " returns [void]");
        else
            Console.WriteLine(mi.Name + " returns [" + (returnValue ?? "null") + "]");
    }

    public void OnError(object obj, MethodInfo mi, object[] args, Exception exception)
    {
        Console.WriteLine("Exception Handled: " + exception.Message);
        throw new ApplicationException(exception.Message, exception);
    }

    private object SetReturnValue(MethodInfo mi, object[] args)
    {
        object res = null;

        if (mi.Name.StartsWith("get_"))
        {
            var propName = mi.Name.Replace("get_", "");
            if (_propertyValues.ContainsKey(propName))
                res = _propertyValues[propName];
        }
        else if (mi.Name.StartsWith("set_"))
        {
            var propName = mi.Name.Replace("set_", "");
            if (!_propertyValues.ContainsKey(propName))
                _propertyValues.Add(propName, args[0]);
            else
                _propertyValues[propName] = args[0];
        }
        else if (mi.IsAbstract && mi.ReturnType != typeof(void))
        {
            res = mi.ReturnType.GetDefaultValue();
            var methodName = mi.Name;
            if (!_propertyValues.ContainsKey(methodName))
                _propertyValues.Add(methodName, res);
            else
                _propertyValues[methodName] = res;
        }

        if (mi.ReturnType == typeof(void))
            Console.WriteLine(mi.Name + " should return [void]");
        else
            Console.WriteLine(mi.Name + " should return [" + res + "]");

        return res;
    }

    private void WriteParameterInfo(MethodInfo mi, object[] args)
    {
        Console.Write(mi.Name + " takes ");
        if (args.Length == 0)
        {
            Console.WriteLine("no parameter");
        }
        else
        {
            Console.WriteLine("{0} parameter(s)", args.Length);
            var paramInfos = mi.GetParameters();
            for (int i = 0; i < args.Length; i++)
            {
                Console.WriteLine("\t[{0} {1}: '{2}']", paramInfos[i].ParameterType.Name, paramInfos[i].Name, args[i]);
            }
        }
    }
}

public interface IInterface1
{
    string Name { get; set; }
    string MethodString(int i, string s, object o);
}

public interface IInterface2
{
    int Value { get; set; }
    int MethodInt(int i, string s, Ogrenci o);
}

public class TestClass
{
    public virtual int PropInt { get; set; }

    public virtual void ThrowException()
    {
        throw new Exception("Custom Error");
    }

    protected virtual double ProtectedSquare(int x)
    {
        Console.WriteLine("Executing Method ProtectedSquare");
        return x * x;
    }

    public virtual double PublicSquare(int x)
    {
        Console.WriteLine("Executing Method PublicSquare");
        return ProtectedSquare(x);
    }

    public virtual string MethodString()
    {
        Console.WriteLine("Executing String Method");
        return "Hele";
    }

    public virtual int MethodInt()
    {
        Console.WriteLine("Executing Int Method");
        return 985;
    }

    public virtual void MethodVoid()
    {
        Console.WriteLine("Executing Void Method");
    }

    public virtual Ogrenci MethodComplex(int x, string f, Ogrenci o)
    {
        Console.WriteLine("Executing Parameter Method");
        return new Ogrenci { Name = o.Name + x + f };
    }
}

public class Ogrenci
{
    public string Name { get; set; }

    public override string ToString()
    {
        return Name;
    }
}
}

这篇关于如何知道我的应用程序代码中何时调用了任何方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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