#c_sharp
Задача следующая. Есть некий обособленный класс Test с методом TestMethod. public Test { public void TestMethod() { //... } } Также есть множество других классов, которые наследуются от одного абстрактного класса и в этих классах большое количество методов. Нужно, чтобы во всех этих методах сначала вызывался TestMethod(), затем шло непосредственно тело самого метода и затем снова вызывался TestMethod(), то есть: public Class1:AbstractClass { public void Method1() { TestMethod() //тело метода TestMethod() } public void Method2() { TestMethod() //тело метода TestMethod() } } Понятное дело, что можно так и прописать в каждом методе каждого класса. Но может есть более изящный способ обернуть тела методов? (!!!) Методы могут иметь разные входные и выходные параметры. Не только void и без параметров.
Ответы
Ответ 1
Вам нужно использовать какой-нибудь 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(i); proxy.M3(); } } Вывод программы: Test::TestMethod (in) Derived::M3 Test::TestMethod (in) Base::M2, arg = 10 Test::TestMethod (out) Test::TestMethod (out) Ответ 2
Как насчёт using? Хотя это и не очень-то корректно семантически: public void Method1(){ using (new TestMethodWrapper()){ //тело метода } } public class TestMethodWrapper : IDisposable { public TestMethodWrapper(){ TestMethod(); } public void Dispose(){ TestMethod(); } }
Комментариев нет:
Отправить комментарий