внедрение внешнего аргумента в вызовы методов в нескольких целевых классах - PullRequest
2 голосов
/ 06 сентября 2011

У меня есть несколько классов, которые вызывают скажем Trace.WriteLine ("LogSomethingClassSpecific"), в различных методах повсюду.Теперь я хотел бы, чтобы некоторые из этих классов делали все свои вызовы Trace следующим образом: Trace.WriteLine ("LogSomethingClassSpecific", "CategoryA")

Но!Я бы хотел добиться этого внешне из одного класса классификатора ;без необходимости находить и изменять каждый вызов Trace в каждом из определенных классов.

Пример архитектуры

  • Class1, Class2, Class3, которые могут или не могут использовать вызовы Trace

  • Отдельный ControllerClass, который позволяет вызывать все существующие вызовы Trace в скажем Class2 и Class3 с добавленным аргументом «CategoryA».При сохранении гибкости легко изменять целевые классы.

Как этого можно достичь?

Возможно ли использование некоторых атрибутов в сочетании с аспектно-ориентированным программированием (AOP) библиотека?например, управляющий класс может указать, на какие классы нацеливаться :

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

И затем перехватывать все вызовы Trace.WriteLine с помощью PostSharp

НоНе знаете, как извлечь контекст вызова, чтобы определить, был ли отмечен класс вызова для включения «CategoryA»?

Или есть альтернативные способы достижения этой цели?

Благодарен за любые мысли.

1 Ответ

1 голос
/ 06 сентября 2011

Есть несколько способов сделать это, но я предполагаю, что вы вызываете Trace в таких местах, как конструкции if / else, так что вот как вы будете делать то, о чем вы просите (по крайней мере, что Я думаю, что вы просите)

    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 вызовами аспекта.

Редактировать : Насколько я знаю, нет способа получить фактическую точку вызова целевого метода. Это означает, что вы должны сделать некоторое отражение во время выполнения. Я обновил код для использования трассировки стека. Вы должны сделать это только один раз (для каждого типа), поскольку время жизни будет для каждого типа, а не для каждого экземпляра, поэтому вы получаете удар только один раз. Это не то, как я бы это сделал, но я предполагаю, что это будет для целей отладки.

...