如何知道我的应用程序代码中何时调用任何方法?

时间:2013-01-30 12:09:50

标签: c# .net .net-4.0 aop

为了好玩,我想写一个方面,比如记录,跟踪或检测/分析。但我不想使用任何已有的AOP框架。

我以前使用过PostSharp,现在ASP.NET MVC引入了动作过滤器,它与aspect / advise注入非常相似,而.NET 4有CodeContracts,它们也非常类似于方面,我有一个我希望我的Aspect API看起来很棒。

我还没有想到的唯一的事情,我相信它是构建AOP库的核心,如何知道何时调用方法?

什么,我一直在看这个callstack吗?我是否查找主UI线程及其同步上下文,以查看是否已分配了一些工作,即是否已获得进入的方法?知道是否要调用方法的方法是什么?

4 个答案:

答案 0 :(得分:1)

有两种方法可以知道是否要调用某个方法。

  1. 您可以从ContextBoundObject继承但是您失去了基类的唯一机会。您可以查看this

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

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

    // 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)中发生异常
    4. 所有这些方法都接受参数,具有方法的对象,当前方法的MethodInfo和传递给方法的aguments。另外,AfterMethodCall获取返回值,OnError获取抛出的异常。

      这是神奇的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;
          }
      }
      }
      

答案 1 :(得分:0)

如果每次只放置一个断点是不够的:

正如您所说,观看Call Stack。只要在你认为合适时放置一个断点。

在Visual Studio中,它非常简单..只需运行程序,当你想要一个断点时,在调试过程中将它设置为你知道即将发生的行。

第三个选项是调用Console.WriteLine MSDN ,即使它不是控制台应用程序。 您将在Output Window Ctrl + W O )中看到结果。

您还可以使用System.Diagnostics.Trace MSDN 在“输出”窗口中进行书写。

答案 2 :(得分:0)

设置一个断点和你想看的方法,如果它被调用

答案 3 :(得分:0)

以上技巧也很好,

您还可以在方法中添加JavaScript警告框。所以你会知道这个方法叫做。

如果要维护日志,可以在数据库中使用日志表,并将日志表中的系统时间的插入查询放在日志时间列中。所以,通过这个方法,你现在将在你的方法中使用。