外部参数注入到多个目标类中的方法调用

时间:2011-09-06 12:09:49

标签: c# design-patterns logging aop postsharp

我有很多类调用说Trace.WriteLine(“LogSomethingClassSpecific”),各种各样的方法。现在我希望其中一些类能够像这样进行所有Trace调用:Trace.WriteLine(“LogSomethingClassSpecific”,“CategoryA”)

但是!我想从一个分类程序类外部实现这个;无需在每个特定类中查找和修改每个Trace调用。

样本架构

  • Class1,Class2,Class3,可能会也可能不会使用跟踪调用

  • 使用添加的参数“CategoryA”调用使用Class2和Class3调用所有现有Trace调用的独立ControllerClass。同时保留了轻松更改目标类的灵活性。

怎么可以实现?

使用某些属性和面向方面编程(AOP)库可能会成为可能吗? 例如 控制班可以specify which classes to target

[assembly: Categorizer("CategoryA", AttributeTargetTypes = "Namespace.ClassB")]

然后intercept all Trace.WriteLine calls with PostSharp

但我不知道提取调用上下文以确定调用类是否已标记为包含“CategoryA”的方法?

或者有其他方法可以实现这一目标吗?

感谢任何想法。

1 个答案:

答案 0 :(得分:1)

有几种方法可以解决这个问题,但我假设你在像if / else构造这样的地方调用Trace,所以这就是你要做的事情(至少,是什么)我想你要求了)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using PostSharp.Aspects;
    using System.Diagnostics;

    [assembly: ConsoleApplication2.TraceIntercept(AttributeTargetAssemblies = "System", AttributeTargetTypes = "System.Diagnostics.Trace")]

    namespace ConsoleApplication2
    {
        class Program
        {
            static void Main(string[] args)
            {
                ExampleA ex = new ExampleA();
                ex.Method1();

                Console.ReadKey();
            }

        }

        public class ExampleA
        {
            public void Method1()
            {
                Trace.Write("Test");
            }

        }

[Serializable]
    [TraceIntercept(AttributeExclude = true)]
    public class TraceIntercept : MethodInterceptionAspect
    {
        private bool addArgument;
        private string typeName = string.Empty;

        public override void OnInvoke(MethodInterceptionArgs args)
        {
            CheckInvocationPoint();

            if (addArgument)
            {
                //Do work. Change arguments, etc.
            }

            args.Proceed(); // Proceed with Trace
        }

        private void CheckInvocationPoint()
        {
            if (string.IsNullOrEmpty(this.typeName))
            {
                StackTrace s = new StackTrace();
                StackFrame f = s.GetFrame(2);
                string className = f.GetMethod().DeclaringType.Name;

                if (classsName.Equals("ExampleA"))
                {
                    addArgument = true;
                }
            }
        }
    }
}

这将拦截对System.Diagnostics.Trace方法的调用,而是调用TraceIntercept.OnInvoke方法,您可以在其中操作Trace调用。这种方式的工作方式是PostSharp只需用对方面的调用替换对Trace.Write的调用。

编辑:据我所知,没有办法获取目标方法的实际调用点。这意味着您必须在运行时进行一些反射。我已经更新了代码以使用堆栈跟踪。您只需要执行一次(每种类型),因为方面生命周期将是每个类型而不是每个实例,所以您只需要一次点击。这不是我会怎么做,但我认为这将用于调试目的。