Задача следующая.
Есть некий обособленный класс Test с методом TestMethod.
public Test
{
public void TestMethod()
{
//...
}
}
Также есть множество других классов, которые наследуются от одного абстрактного класса и в этих классах большое количество методов.
Нужно, чтобы во всех этих методах сначала вызывался TestMethod(), затем шло непосредственно тело самого метода и затем снова вызывался TestMethod(), то есть:
public Class1:AbstractClass
{
public void Method1()
{
TestMethod()
//тело метода
TestMethod()
}
public void Method2()
{
TestMethod()
//тело метода
TestMethod()
}
}
Понятное дело, что можно так и прописать в каждом методе каждого класса. Но может есть более изящный способ обернуть тела методов?
(!!!) Методы могут иметь разные входные и выходные параметры. Не только void и без параметров.
Ответ
Вам нужно использовать какой-нибудь AOP-фреймворк. Вот тут есть большой их список.
Давайте сделаем пример с популярным Castle.DynamicProxy
Отмечу сразу, нам нужно будет модифицировать код. Перехватываемые методы (то есть, те методы, к которым мы «добавляем» вызов TestMethod) должны быть виртуальными. Если это — слишком большое ограничение, вам понадобится другой AOP-фреймворк (например, PostSharp).
Пусть наш код такой:
class Program
{
static void Main(string[] args)
{
var derived = new Derived();
derived.M3();
}
}
class Base
{
public void M1()
{
Console.WriteLine("Base::M1");
}
public int M2(int arg)
{
Console.WriteLine($"Base::M2, arg = {arg}");
return arg + 1;
}
}
class Derived : Base
{
public int M3()
{
Console.WriteLine("Derived::M3");
return M2(10);
}
}
и тестовый класс
class Test
{
public static void TestMethod(bool entry)
{
Console.WriteLine($"Test::TestMethod ({(entry ? "in" : "out")})");
}
}
Подключим через nuget Castle.Core, и допишем наш интерсептор:
using Castle.DynamicProxy;
public class Interceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Test.TestMethod();
try
{
invocation.Proceed();
}
finally
{
Test.TestMethod();
}
}
}
Затем (ограничение Castle.Proxy) нам нужно сделать наши классы публичными, а методы виртуальными. Получаем такой изменённый код:
public class Base
{
public virtual void M1()
{
Console.WriteLine("Base::M1");
}
public virtual int M2(int arg)
{
Console.WriteLine($"Base::M2, arg = {arg}");
return arg + 1;
}
}
public class Derived : Base
{
public virtual int M3()
{
Console.WriteLine("Derived::M3");
return M2(10);
}
}
Меняем Main
class Program
{
static void Main(string[] args)
{
var i = new Interceptor();
var proxy = new ProxyGenerator().CreateClassProxy
Вывод программы:
Test::TestMethod (in)
Derived::M3
Test::TestMethod (in)
Base::M2, arg = 10
Test::TestMethod (out)
Test::TestMethod (out)
Комментариев нет:
Отправить комментарий