Acabo de ver esta charla de Greg Young advirtiendo a la gente a KISS: Keep It Simple Stupid.
Una de las cosas que él sugiere es que para hacer la programación orientada a aspectos, uno qué no se necesita un marco .
Comienza haciendo una fuerte restricción: que todos los métodos toman uno, y solo un parámetro, (aunque lo relaja un poco más tarde usando una aplicación parcial ).
El ejemplo que da es definir una interfaz:
public interface IConsumes<T>
{
void Consume(T message);
}
Si queremos emitir un comando:
public class Command
{
public string SomeInformation;
public int ID;
public override string ToString()
{
return ID + " : " + SomeInformation + Environment.NewLine;
}
}
El comando se implementa como:
public class CommandService : IConsumes<Command>
{
private IConsumes<Command> _next;
public CommandService(IConsumes<Command> cmd = null)
{
_next = cmd;
}
public void Consume(Command message)
{
Console.WriteLine("Command complete!");
if (_next != null)
_next.Consume(message);
}
}
Para iniciar sesión en la consola, uno solo implementa:
public class Logger<T> : IConsumes<T>
{
private readonly IConsumes<T> _next;
public Logger(IConsumes<T> next)
{
_next = next;
}
public void Consume(T message)
{
Log(message);
if (_next != null)
_next.Consume(message);
}
private void Log(T message)
{
Console.WriteLine(message);
}
}
Entonces, el registro previo al comando, el servicio de comando y el registro posterior al comando son solo:
var log1 = new Logger<Command>(null);
var svr = new CommandService(log);
var startOfChain = new Logger<Command>(svr);
y el comando es ejecutado por:
var cmd = new Command();
startOfChain.Consume(cmd);
Para hacer esto en, por ejemplo, PostSharp , uno anotaría deCommandService
esta manera:
public class CommandService : IConsumes<Command>
{
[Trace]
public void Consume(Command message)
{
Console.WriteLine("Command complete!");
}
}
Y luego tiene que implementar el registro en una clase de atributo algo así como:
[Serializable]
public class TraceAttribute : OnMethodBoundaryAspect
{
public override void OnEntry( MethodExecutionArgs args )
{
Console.WriteLine(args.Method.Name + " : Entered!" );
}
public override void OnSuccess( MethodExecutionArgs args )
{
Console.WriteLine(args.Method.Name + " : Exited!" );
}
public override void OnException( MethodExecutionArgs args )
{
Console.WriteLine(args.Method.Name + " : EX : " + args.Exception.Message );
}
}
El argumento que usa Greg es que la conexión del atributo a la implementación del atributo es "demasiada magia" para poder explicar lo que le está sucediendo a un desarrollador junior. El ejemplo inicial es todo "solo código" y se explica fácilmente.
Entonces, después de esa acumulación bastante larga, la pregunta es: ¿cuándo cambias el enfoque no marco de Greg para usar algo como PostSharp para AOP?
IConsumes
piezas diferentes . En lugar de tener que usar XML externo o alguna interfaz fluida, otra cosa más que aprender. Se podría argumentar que esta metodología es "otra cosa para aprender" también.