Этого можно добиться с помощью функции Перехват контейнера DI, например Castle Windsor . Действительно, можно настроить контейнер таким образом, чтобы все классы, у которых есть метод, декорированный определенным атрибутом, были бы перехвачены.
Что касается пункта № 3, OP запросил решение без AOP-фреймворка. В следующем ответе я предположил, что следует избегать Aspect, JointPoint, PointCut и т.д.
Настройка общей регистрации перехватчика на основе наличия атрибута:
public class RequireInterception : IContributeComponentModelConstruction
{
public void ProcessModel(IKernel kernel, ComponentModel model)
{
if (HasAMethodDecoratedByLoggingAttribute(model.Implementation))
{
model.Interceptors.Add(new InterceptorReference(typeof(ConsoleLoggingInterceptor)));
model.Interceptors.Add(new InterceptorReference(typeof(NLogInterceptor)));
}
}
private bool HasAMethodDecoratedByLoggingAttribute(Type implementation)
{
foreach (var memberInfo in implementation.GetMembers())
{
var attribute = memberInfo.GetCustomAttributes(typeof(LogAttribute)).FirstOrDefault() as LogAttribute;
if (attribute != null)
{
return true;
}
}
return false;
}
}
Добавить созданную IContributeComponentModelConstruction в контейнер
container.Kernel.ComponentModelBuilder.AddContributor(new RequireInterception());
И вы можете делать что угодно в самом перехватчике
public class ConsoleLoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.Writeline("Log before executing");
invocation.Proceed();
Console.Writeline("Log after executing");
}
}
Добавьте атрибут logging к вашему методу в log
public class Traced
{
[Log]
public void Method1(String name, Int32 value) { }
[Log]
public void Method2(Object object) { }
}
Обратите внимание, что некоторая обработка атрибута потребуется, если требуется перехватить только какой-либо метод класса. По умолчанию все открытые методы будут перехвачены.