Related
I'm looking for a way to implement the following.
I want to be able to register "ActionHandlers" as services in my DI Container, for this purpose I have made the following interfaces:
public interface IActionHandler {
Task HandleAsync(IAction action);
}
public interface IActionHandler<T> : IActionHandler where T : IAction, new() {
Task HandleAsync(T action);
}
My idea was then to create a derived type called ActionHandlerContainer:
public class ActionHandlerContainer : IActionHandler {
private readonly Dictionary<Type, IActionHandler> _handlers;
public ActionHandlerContainer(IEnumerable<IActionHandler<??T??>>) {
// What to do here?.
// As this ActionHandlerContainer class is registered as a service,
// I expect the DI container in return to inject all my ActionHandler services here.
}
public Task HandleAsync(IAction action) {
// Fetch appropriate handler from the map.
_handlers.TryGetValue(action.getType(), out var actionHandler);
if(actionHandler == null) {
throw new Exception($"No handler could be found for the Action of type: {action.GetType()}");
}
// Invoke the correct handler.
return actionHandler.HandleAsync(action);
}
}
Which would take in any action and delegate it to the correct handler, an example handler could look like:
public class SetColorActionHandler : IActionHandler<SetColorAction> {
public async Task HandleAsync(SetColorAction action) {
return await ComponentManager.SetComponentColor(action);
}
}
The DI container service registration would look like this (I suppose)
builder.Services.AddTransient<IActionHandler<SetColorAction>, SetColorActionHandler>();
builder.Services.AddSingleton<ActionHandlerContainer>();
Some open questions I have myself is:
Should multiple ActionHandlers be able to be registered to one action..
Is it possible to implement the decorator pattern on top of this, say I want a ConsoleDebugLoggingSetColorActionHandler which decorates the original SetColorActionHandler.
A problem I have right now is if IActionHandler implements IActionHandler, then any IActionHandler implementation has to implement the code async Task HandleAsync(IAction action) method which seems duplicative.
So my question is, given the code examples and explanations, how can I implement this properly?
Thanks in advance, any help is appreciated,
Nicky.
[EDIT1]:
I tried the following in ActionHandlerContainer::HandleAsync
public Task HandleAsync(IAction action) {
Type runtimeType = action.GetType();
var _handler = _serviceProvider.GetService(typeof(IActionHandler<runtimeType>));
}
But this does not seem to work.
[EDIT2]:
Providing some context for vendettamit:
public class MqttClientWrapper {
...<omitted>
private Task ClientOnApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg) {
Console.WriteLine("The client received an application message.");
arg.DumpToConsole();
// Create the ActionPayload from the MQTT Application Message's Payload.
var actionPayload = ActionPayload.FromPayload(arg.ApplicationMessage.Payload);
// Grab the correct action type from the map according to the identifier in the payload.
var actionType = ActionMap.ActionIdentifierToActionType[actionPayload.ActionIdentifier];
// Now instruct the factory to instantiate that type of action.
var action = _actionFactory.CreateAction(actionPayload.ActionData, actionType);
// Finally, pass on the action to the correct handler.
_actionHandlerContainer.HandleAsync(action);
return Task.CompletedTask;
}
}
One suggestion: Use MediatR. In the past I've railed against it, but I've softened. It's not perfect, but it's a thorough implementation of what you're trying to solve.
Or, here's a detailed custom approach.
As you noted in your question, the issue is that if you're going to have a collection of IActionHandlers<T> but T is different for each one, then what is the type of the collection?
Any solution will involve some sort of reflection or type-checking. (That's inevitable. You're starting with an IAction, but you don't want an IActionHandler<IAction> - you want individual handlers for specific implementations of IAction.) Even though I don't usually use object, it's okay as long as my code ensures that the object will be the expected type. That is, given type T, you're going to get an object which can be cast as IActionHandler<T>.
Here's an approach. I use the terms "command" and "command handler" instead of "action" and "action handler." There's some reflection involved, but it does the job. Even if it's not exactly what you need, it might give you some ideas.
First, some interfaces:
public interface ICommand
{
}
public interface ICommandHandler
{
Task HandleAsync(ICommand command);
}
public interface ICommandHandler<TCommand> where TCommand : ICommand
{
Task HandleAsync(TCommand command);
}
ICommand marks a class which is used as a command.
ICommandHandler is the interface for a class that takes any ICommand and "routes" it to a specific command handler. It's the equivalent of IActionHandler in your question.
ICommandHandler<T> is the interface for the type-specific command handler.
Here's the implementation of ICommandHandler. This has to
receive a command
resolve an instance of the concrete handler for that command type
invoke the handler, passing the command to it.
public class CommandHandler : ICommandHandler
{
private readonly Func<Type, object> _getHandler;
public CommandHandler(Func<Type, object> getHandler)
{
_getHandler = getHandler;
}
public async Task HandleAsync(ICommand command)
{
var commandHandlerType = GetCommandHandlerType(command);
var handler = _getHandler(commandHandlerType);
await InvokeHandler(handler, command);
}
private Type GetCommandHandlerType(ICommand command)
{
return typeof(ICommandHandler<>).MakeGenericType(command.GetType());
}
// See the notes below. This reflection could be "cached"
// in a Dictionary<Type, MethodInfo> so that once you find the "handle"
// method for a specific type you don't have to repeat the reflection.
private async Task InvokeHandler(object handler, ICommand command)
{
var handlerMethod = handler.GetType().GetMethods()
.Single(method => IsHandleMethod(method, command.GetType()));
var task = (Task)handlerMethod.Invoke(handler, new object[] { command });
await task.ConfigureAwait(false);
}
private bool IsHandleMethod(MethodInfo method, Type commandType)
{
if (method.Name != nameof(ICommandHandler.HandleAsync)
|| method.ReturnType != typeof(Task))
{
return false;
}
var parameters = method.GetParameters();
return parameters.Length == 1 && parameters[0].ParameterType == commandType;
}
}
Here's what this does when public async Task HandleAsync(ICommand command) is called:
Determines the generic type of the handler for the command. If the command type is FooCommand then the generic command handler type is ICommandHandler<FooCommand>.
Calls Func<Type, object> _getHandler to get a concrete instance of the command handler. That function is injected. What is the implementation of that function? More on that later. But the point is that as far as this class is concerned, it can pass the handler type to this function and get back a handler.
Finds the "handle" method on the handler type.
Invokes the handle method on the concrete handler, passing the command.
There's room for improvement here. Once it finds the method for a type it could add it to a Dictionary<Type, MethodInfo> to avoid that reflection again. It could even create a function that performs the whole invocation and add it to a Dictionary<Type, Func<Object, Task>. Either of those would improve performance.
(If that sounds convoluted, then once again that's a reason to consider using MediatR. There are a few details about it that I don't like, but does all this work. It also handles more complex scenarios like handlers that return something or handlers that use a CancellationToken.)
That leaves the question - what is the Func<Type, object> that takes a command type and returns the correct command handler?
If you're using IServiceCollection/IServiceProvider, these extensions register everything and provide that. (The point is that injecting the function means that we're not tied to that specific IoC container.)
public static class CommandHandlerServiceCollectionExtensions
{
public static IServiceCollection AddCommandHandling(this IServiceCollection services)
{
services.AddSingleton<ICommandHandler>(provider => new CommandHandler(handlerType =>
{
return provider.GetRequiredService(handlerType);
}
));
return services;
}
public static IServiceCollection AddHandlersFromAssemblyContainingType<T>(this IServiceCollection services)
where T : class
{
var assembly = typeof(T).Assembly;
IEnumerable<Type> types = assembly.GetTypes().Where(type => !type.IsAbstract && !type.IsInterface);
foreach (Type type in types)
{
Type[] typeInterfaces = type.GetInterfaces();
foreach (Type typeInterface in typeInterfaces)
{
if (typeInterface.IsGenericType && typeInterface.GetGenericTypeDefinition() == typeof(ICommandHandler<>))
{
services.AddScoped(typeInterface, type);
}
}
}
return services;
}
}
The first method registers CommandHandler as the implementation of ICommandHandler. The implementation of Func<Type, object> is
handlerType =>
{
return provider.GetRequiredService(handlerType);
}
In other words, whatever the handler type is, resolve it from the IServiceProvider. If the type is ICommandHander<FooCommand> then it's going to resolve whatever implementation of that interface is registered.
This dependency on the IServiceProvider at runtime is not a service locator. (Everything ultimately depends on it at runtime.) CommandHandler depends on an abstraction - a function - not IServiceProvider. The use of the IoC container is all in the composition root.
You could manually register each one of those implementations:
serviceCollection.AddScoped<ICommandHander<FooCommand>, FooCommandHandler>();
...etc. The second extension does that for you. It discovers implementations of ICommandHandler<T> and registers them with the IServiceCollection.
I have used this in production code. If I wanted it to be more robust I'd add handling for cancellation tokens and maybe return types. (I could be lazy and argue that return types violate command/query separation.) It would require updating how InvokeHandler selects a method on the handler to invoke.
And because nothing is complete without tests, here's a test.
It's convoluted. It creates a command which contains both a list and a number. The command handler adds the number to the list. The point is that it's observable. The test only passes if the handler gets registered, resolved, and invoked so that the number gets added to the list.
[TestClass]
public class CommandHandlerTests
{
[TestMethod]
public async Task CommandHandler_Invokes_Correct_Handler()
{
var serviceCollection = new ServiceCollection();
serviceCollection
.AddCommandHandling()
.AddHandlersFromAssemblyContainingType<AddNumberToListCommand>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var commandHandler = serviceProvider.GetRequiredService<ICommandHandler>();
var list = new List<int>();
var command = new AddNumberToListCommand(list, 1);
// This is the non-generic ICommandHandler interface
await commandHandler.HandleAsync(command);
Assert.IsTrue(list.Contains(1));
}
}
public class AddNumberToListCommand : ICommand
{
public AddNumberToListCommand(List<int> listOfNumbers, int numberToAdd)
{
ListOfNumbers = listOfNumbers;
NumberToAdd = numberToAdd;
}
public List<int> ListOfNumbers { get; }
public int NumberToAdd { get; }
}
public class AddNumberToListHandler : ICommandHandler<AddNumberToListCommand>
{
public Task HandleAsync(AddNumberToListCommand command)
{
command.ListOfNumbers.Add(command.NumberToAdd);
return Task.CompletedTask;
}
}
So what I like:
You're thinking "Open/Closed Principle". That's good.
What I don't like.
Your Dictionary has "Type" as a Key. Thus you're trying to store EVERY Type to its 1:N IActionHandler's in one place.
(By the way, you'll probably get a Key-Exists error (or it would just overwrite the single) if you tried to register 2:N IActionHandlers for a single Type.
I would move toward:
public class ActionHandlerContainer<T> : IActionHandler<T> {
private readonly IDictionary<int, IActionHandler<T>> _handlers;
and "inject" your specific to a single T 1:N concrete handlers.
Notice, I've removed the "Type", and changed to an int? Why an int? Because if you want to control the ORDER of the injected items. You can loop over the IDictionary (int) Keys (in order).
So how would this play out?
You don't register a single ActionHandlerContainer (with all the types)
You register something like
(ioc register the below)
ActionHandlerContainer<Employee>
and you constructor inject your 1:N EmployeeHandler(s) into the above.
then you register something like (a different "Type")
(ioc register the below)
ActionHandlerContainer<Candy>
You are not using Generics to be a "Type holder of everything". You use Generics to reduce copies of code. (so you don't have to write a "copy" for just Employee, and another copy for "Candy".....
Somewhere you need to inject the
ActionHandlerContainer<Employee> ahce
...
public EmployeeManager : IEmployeeManager
private readonly ActionHandlerContainer<Employee> theAhce;
public EmployeeManager(ActionHandlerContainer<Employee> ahce)
{
this.thheAhce = ahce; /* simple code, you should actually check for null on the input ahce to make sure its not null */
}
public void UpdateEmployee(Employee emp)
{
this.theAhce.Invoke(emp); /* << and this will of course run your 1:N EMPLOYEE handlers */
}
Something like that.
IMHO, get rid of the "holds ALL types" mentality.
For a given class I would like to have tracing functionality i.e. I would like to log every method call (method signature and actual parameter values) and every method exit (just the method signature).
How do I accomplish this assuming that:
I don't want to use any 3rd party
AOP libraries for C#,
I don't want to add duplicate code to all the methods that I want to trace,
I don't want to change the public API of the class - users of the class should be able to call all the methods in exactly the same way.
To make the question more concrete let's assume there are 3 classes:
public class Caller
{
public static void Call()
{
Traced traced = new Traced();
traced.Method1();
traced.Method2();
}
}
public class Traced
{
public void Method1(String name, Int32 value) { }
public void Method2(Object object) { }
}
public class Logger
{
public static void LogStart(MethodInfo method, Object[] parameterValues);
public static void LogEnd(MethodInfo method);
}
How do I invoke Logger.LogStart and Logger.LogEnd for every call to Method1 and Method2 without modifying the Caller.Call method and without adding the calls explicitly to Traced.Method1 and Traced.Method2?
Edit: What would be the solution if I'm allowed to slightly change the Call method?
C# is not an AOP oriented language. It has some AOP features and you can emulate some others but making AOP with C# is painful.
I looked up for ways to do exactly what you wanted to do and I found no easy way to do it.
As I understand it, this is what you want to do:
[Log()]
public void Method1(String name, Int32 value);
and in order to do that you have two main options
Inherit your class from MarshalByRefObject or ContextBoundObject and define an attribute which inherits from IMessageSink. This article has a good example. You have to consider nontheless that using a MarshalByRefObject the performance will go down like hell, and I mean it, I'm talking about a 10x performance lost so think carefully before trying that.
The other option is to inject code directly. In runtime, meaning you'll have to use reflection to "read" every class, get its attributes and inject the appropiate call (and for that matter I think you couldn't use the Reflection.Emit method as I think Reflection.Emit wouldn't allow you to insert new code inside an already existing method). At design time this will mean creating an extension to the CLR compiler which I have honestly no idea on how it's done.
The final option is using an IoC framework. Maybe it's not the perfect solution as most IoC frameworks works by defining entry points which allow methods to be hooked but, depending on what you want to achive, that might be a fair aproximation.
The simplest way to achieve that is probably to use PostSharp. It injects code inside your methods based on the attributes that you apply to it. It allows you to do exactly what you want.
Another option is to use the profiling API to inject code inside the method, but that is really hardcore.
You could achieve it with Interception feature of a DI container such as Castle Windsor. Indeed, it is possible to configure the container in such way that every classes that have a method decorated by a specific attribute would be intercepted.
Regarding point #3, OP asked for a solution without AOP framework. I assumed in the following answer that what should be avoided were Aspect, JointPoint, PointCut, etc. According to Interception documentation from CastleWindsor, none of those are required to accomplish what is asked.
Configure generic registration of an Interceptor, based on the presence of an attribute:
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;
}
}
Add the created IContributeComponentModelConstruction to container
container.Kernel.ComponentModelBuilder.AddContributor(new RequireInterception());
And you can do whatever you want in the interceptor itself
public class ConsoleLoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.Writeline("Log before executing");
invocation.Proceed();
Console.Writeline("Log after executing");
}
}
Add the logging attribute to your method to log
public class Traced
{
[Log]
public void Method1(String name, Int32 value) { }
[Log]
public void Method2(Object object) { }
}
Note that some handling of the attribute will be required if only some method of a class needs to be intercepted. By default, all public methods will be intercepted.
If you write a class - call it Tracing - that implements the IDisposable interface, you could wrap all method bodies in a
Using( Tracing tracing = new Tracing() ){ ... method body ...}
In the Tracing class you could the handle the logic of the traces in the constructor/Dispose method, respectively, in the Tracing class to keep track of the entering and exiting of the methods. Such that:
public class Traced
{
public void Method1(String name, Int32 value) {
using(Tracing tracer = new Tracing())
{
[... method body ...]
}
}
public void Method2(Object object) {
using(Tracing tracer = new Tracing())
{
[... method body ...]
}
}
}
If you want to trace after your methods without limitation (no code adaptation, no AOP Framework, no duplicate code), let me tell you, you need some magic...
Seriously, I resolved it to implement an AOP Framework working at runtime.
You can find here : NConcern .NET AOP Framework
I decided to create this AOP Framework to give a respond to this kind of needs. it is a simple library very lightweight. You can see an example of logger in home page.
If you don't want to use a 3rd party assembly, you can browse the code source (open source) and copy both files Aspect.Directory.cs and Aspect.Directory.Entry.cs to adapted as your wishes. Theses classes allow to replace your methods at runtime. I would just ask you to respect the license.
I hope you will find what you need or to convince you to finally use an AOP Framework.
Take a look at this - Pretty heavy stuff..
http://msdn.microsoft.com/en-us/magazine/cc164165.aspx
Essential .net - don box had a chapter on what you need called Interception.
I scraped some of it here (Sorry about the font colors - I had a dark theme back then...)
http://madcoderspeak.blogspot.com/2005/09/essential-interception-using-contexts.html
I have found a different way which may be easier...
Declare a Method InvokeMethod
[WebMethod]
public object InvokeMethod(string methodName, Dictionary<string, object> methodArguments)
{
try
{
string lowerMethodName = '_' + methodName.ToLowerInvariant();
List<object> tempParams = new List<object>();
foreach (MethodInfo methodInfo in serviceMethods.Where(methodInfo => methodInfo.Name.ToLowerInvariant() == lowerMethodName))
{
ParameterInfo[] parameters = methodInfo.GetParameters();
if (parameters.Length != methodArguments.Count()) continue;
else foreach (ParameterInfo parameter in parameters)
{
object argument = null;
if (methodArguments.TryGetValue(parameter.Name, out argument))
{
if (parameter.ParameterType.IsValueType)
{
System.ComponentModel.TypeConverter tc = System.ComponentModel.TypeDescriptor.GetConverter(parameter.ParameterType);
argument = tc.ConvertFrom(argument);
}
tempParams.Insert(parameter.Position, argument);
}
else goto ContinueLoop;
}
foreach (object attribute in methodInfo.GetCustomAttributes(true))
{
if (attribute is YourAttributeClass)
{
RequiresPermissionAttribute attrib = attribute as YourAttributeClass;
YourAttributeClass.YourMethod();//Mine throws an ex
}
}
return methodInfo.Invoke(this, tempParams.ToArray());
ContinueLoop:
continue;
}
return null;
}
catch
{
throw;
}
}
I then define my methods like so
[WebMethod]
public void BroadcastMessage(string Message)
{
//MessageBus.GetInstance().SendAll("<span class='system'>Web Service Broadcast: <b>" + Message + "</b></span>");
//return;
InvokeMethod("BroadcastMessage", new Dictionary<string, object>() { {"Message", Message} });
}
[RequiresPermission("editUser")]
void _BroadcastMessage(string Message)
{
MessageBus.GetInstance().SendAll("<span class='system'>Web Service Broadcast: <b>" + Message + "</b></span>");
return;
}
Now I can have the check at run time without the dependency injection...
No gotchas in site :)
Hopefully you will agree that this is less weight then a AOP Framework or deriving from MarshalByRefObject or using remoting or proxy classes.
First you have to modify your class to implement an interface (rather than implementing the MarshalByRefObject).
interface ITraced {
void Method1();
void Method2()
}
class Traced: ITraced { .... }
Next you need a generic wrapper object based on RealProxy to decorate any interface to allow intercepting any call to the decorated object.
class MethodLogInterceptor: RealProxy
{
public MethodLogInterceptor(Type interfaceType, object decorated)
: base(interfaceType)
{
_decorated = decorated;
}
public override IMessage Invoke(IMessage msg)
{
var methodCall = msg as IMethodCallMessage;
var methodInfo = methodCall.MethodBase;
Console.WriteLine("Precall " + methodInfo.Name);
var result = methodInfo.Invoke(_decorated, methodCall.InArgs);
Console.WriteLine("Postcall " + methodInfo.Name);
return new ReturnMessage(result, null, 0,
methodCall.LogicalCallContext, methodCall);
}
}
Now we are ready to intercept calls to Method1 and Method2 of ITraced
public class Caller
{
public static void Call()
{
ITraced traced = (ITraced)new MethodLogInterceptor(typeof(ITraced), new Traced()).GetTransparentProxy();
traced.Method1();
traced.Method2();
}
}
You can use open source framework CInject on CodePlex. You can write minimal code to create an Injector and get it to intercept any code quickly with CInject. Plus, since this is Open Source you can extend this as well.
Or you can follow the steps mentioned on this article on Intercepting Method Calls using IL and create your own interceptor using Reflection.Emit classes in C#.
I don't know a solution but my approach would be as follows.
Decorate the class (or its methods) with a custom attribute. Somewhere else in the program, let an initialization function reflect all types, read the methods decorated with the attributes and inject some IL code into the method. It might actually be more practical to replace the method by a stub that calls LogStart, the actual method and then LogEnd. Additionally, I don't know if you can change methods using reflection so it might be more practical to replace the whole type.
You could potentially use the GOF Decorator Pattern, and 'decorate' all classes that need tracing.
It's probably only really practical with an IOC container (but as pointer out earlier you may want to consider method interception if you're going to go down the IOC path).
you need to bug Ayende for an answer on how he did it:
http://ayende.com/Blog/archive/2009/11/19/can-you-hack-this-out.aspx
AOP is a must for clean code implementing, however if you want to surround a block in C#, generic methods have relatively easier usage. (with intelli sense and strongly typed code) Certainly, it can NOT be an alternative for AOP.
Although PostSHarp have little buggy issues (i do not feel confident for using at production), it is a good stuff.
Generic wrapper class,
public class Wrapper
{
public static Exception TryCatch(Action actionToWrap, Action<Exception> exceptionHandler = null)
{
Exception retval = null;
try
{
actionToWrap();
}
catch (Exception exception)
{
retval = exception;
if (exceptionHandler != null)
{
exceptionHandler(retval);
}
}
return retval;
}
public static Exception LogOnError(Action actionToWrap, string errorMessage = "", Action<Exception> afterExceptionHandled = null)
{
return Wrapper.TryCatch(actionToWrap, (e) =>
{
if (afterExceptionHandled != null)
{
afterExceptionHandled(e);
}
});
}
}
usage could be like this (with intelli sense of course)
var exception = Wrapper.LogOnError(() =>
{
MessageBox.Show("test");
throw new Exception("test");
}, "Hata");
Maybe it's to late for this answer but here it goes.
What you are looking to achieve is built in MediatR library.
This is my RequestLoggerBehaviour which intercepts all calls to my business layer.
namespace SmartWay.Application.Behaviours
{
public class RequestLoggerBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
private readonly ILogger _logger;
private readonly IAppSession _appSession;
private readonly ICreateLogGrain _createLogGrain;
public RequestLoggerBehaviour(ILogger<TRequest> logger, IAppSession appSession, IClusterClient clusterClient)
{
_logger = logger;
_appSession = appSession;
_createLogGrain = clusterClient.GetGrain<ICreateLogGrain>(Guid.NewGuid());
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var name = typeof(TRequest).Name;
_logger.LogInformation($"SmartWay request started: ClientId: {_appSession.ClientId} UserId: {_appSession.UserId} Operation: {name} Request: {request}");
var response = await next();
_logger.LogInformation($"SmartWay request ended: ClientId: {_appSession.ClientId} UserId: {_appSession.UserId} Operation: {name} Request: {request}");
return response;
}
}
}
You can also create performance behaviours to trace methods that take too long to execute for example.
Having clean architecture (MediatR) on your business layer will allow you to keep your code clean while you enforce SOLID principles.
You can see how it works here:
https://youtu.be/5OtUm1BLmG0?t=1
Write your own AOP library.
Use reflection to generate a logging proxy over your instances (not sure if you can do it without changing some part of your existing code).
Rewrite the assembly and inject your logging code (basically the same as 1).
Host the CLR and add logging at this level (i think this is the hardest solution to implement, not sure if you have the required hooks in the CLR though).
The best you can do before C# 6 with 'nameof' released is to use slow StackTrace and linq Expressions.
E.g. for such method
public void MyMethod(int age, string name)
{
log.DebugTrace(() => age, () => name);
//do your stuff
}
Such line may be produces in your log file
Method 'MyMethod' parameters age: 20 name: Mike
Here is the implementation:
//TODO: replace with 'nameof' in C# 6
public static void DebugTrace(this ILog log, params Expression<Func<object>>[] args)
{
#if DEBUG
var method = (new StackTrace()).GetFrame(1).GetMethod();
var parameters = new List<string>();
foreach(var arg in args)
{
MemberExpression memberExpression = null;
if (arg.Body is MemberExpression)
memberExpression = (MemberExpression)arg.Body;
if (arg.Body is UnaryExpression && ((UnaryExpression)arg.Body).Operand is MemberExpression)
memberExpression = (MemberExpression)((UnaryExpression)arg.Body).Operand;
parameters.Add(memberExpression == null ? "NA" : memberExpression.Member.Name + ": " + arg.Compile().DynamicInvoke().ToString());
}
log.Debug(string.Format("Method '{0}' parameters {1}", method.Name, string.Join(" ", parameters)));
#endif
}
I have a class setup in the following manner:
public abstract FooClass {
public FooClass() {
// init stuff;
}
public void RandomMethod() {
// do stuff;
}
public abstract WhatIWantToShim();
}
What I want to do is set the WhatIWantToShim on the ShimFooClass like so:
ShimFooClass.AllInstances.WhatIWantToShim = () => Boo();
I can set RandomMethod just fine,
ShimFooClass.AllInstances.RandomMethod = () => CalculatePi();
However, it appears that the generated ShimFooClass does not create the WhatIWantToShim property on the AllInstances property of the ShimFooClass.
I've looked at http://msdn.microsoft.com/en-us/library/hh549176.aspx#bkmk_shim_basics but I don't see anything there about abstract methods. The only thing I see referenced that is not supported is finalizers. Anybody know what is going on here and if this scenario is supported?
Ahhh....bummer
Interfaces and abstract methods. Stubs provide implementations of interfaces and abstract methods that can be used in testing. Shims can’t instrument interfaces and abstract methods, because they don’t have method bodies.
http://msdn.microsoft.com/en-us/library/hh549175(v=vs.110).aspx
Update: what can be done though is stubbing the shim.
using (ShimsContext.Create())
{
bool wasAbstractMethodCalled = false;
var targetStub = new StubFooClass()
{
WhatIWantToShim01 = () => wasAbstractMethodCalled = true
};
var targetShim = new ShimFooClass(targetStub);
targetShim.AllInstances.RandomMethod = () => CalculatePi();
FooClass target = targetShim.Instance;
target.WhatIWantToShim();
Assert.IsTrue(wasAbstractMethodCalled, "The WhatIWantToShim method was not called.");
}
Since the shim cannot handle detouring the WhatIWantToShim method and the stub can, just create a new instance of the stub class and set the detour handler for the abstract method. (Note: the 01 tagged on the end of WhatIWantToShim was added automatically for me when the Fakes were generated in my actual code).
Then just pass the instantiated stub to the constructor of the shim class and shim away as needed.
I'm replying here because I'm quite sure the other answer did not answer the question, and so that future searches return useful information.
Firstly, you cannot shim interfaces. An abstract method is equivalent to an interface. Furthermore, there is no reason to.
{
bool wasAbstractMethodCalled = false;
var targetStub = new StubFooClass()
{
WhatIWantToShim01 = () => wasAbstractMethodCalled = true
};
ShimFooClass.AllInstances.RandomMethod = #class => targetStub.CalculatePi();
targetStub.WhatIWantToShim();
Assert.IsTrue(wasAbstractMethodCalled, "The WhatIWantToShim method was not called.");
}
The above is a simplified version of a previous answer, and will simply call the action you just assigned. This is probably not your intent.
Remember WHY you shim. You shim when you want to avoid the effects of a method call within a method you are testing. The abstract method can have no body, and therefore cannot affect anything. The only time this would be useful is in a child class, where the shim would be available to you in the first place.
The only situation in which you might have an issue is if a third class is secretly holding an instance of the abstract class and instantiating it with the child class. You can't fake that. It is, however, terrible design; the instance should be coming from some method (which you can shim) or passed in (Because DI is a good thing!) or else the abstraction is worthless, and you may as well have the instance declared to be the child type, since you aren't using the abstraction in any way.
IModificationRequst<Employee> req = new ModificationRequst();
Locator.Instance.GetService<IModificationRequstHandler<Employee>>().Handle(req);
I have a service locator that locates services that returns instances of objects implementing IModificationRequstHandler.
I am trying to modify it to rather than returning a IModificationRequstHandler implementer, it is just internally finds the service and invokes it's handler method, so the above 2 lines would look like this instead:
IModificationRequst<Employee> req = new ModificationRequst();
Locator.Instance.HandleRequest<IModificationRequst<Employee>>(req);
But having hard time with the generics, is there an already established pattern for resovling the requests to their proper request handlers and invoking their handling, rather than getting a handler and then invoking their Handle method from the client?
That violates Single Responsibility Principle. You should not make the service locator implement logic for different services.
If you do want to use static classes you should add another one:
public static class RequestHandler
{
public static void Handle<T>(T request)
{
Locator.Instance.GetService<IModificationRequstHandler<T>>().Handle(req);
}
}
And then:
IModificationRequst<Employee> req = new ModificationRequst();
RequestHandler.Handle(req);
(Sidenote: You might look up Dependency Injection & IoC containers since it makes the code more maintainable)
Your HandleRequest method in the locator class should be defined as follows (assuming Handle has a return type of void):
public void HandleRequest<T>(IModificationRequest<T> req)
{
IModificationRequstHandler<T> handler = GetService<IModificationRequest<T>>();
handler.Handle(req);
}
and your IModificationRequstHandler interface should be defined as follows:
public interface IModificationRequstHandler<T>
{
void Handle(IModificationRequst<T> req);
}
and your call will then become:
Locator.Instance.HandleRequest(req);
The generic type parameter Employee here is inferred from the parameter value req and thus does not need to be specified.
For a given class I would like to have tracing functionality i.e. I would like to log every method call (method signature and actual parameter values) and every method exit (just the method signature).
How do I accomplish this assuming that:
I don't want to use any 3rd party
AOP libraries for C#,
I don't want to add duplicate code to all the methods that I want to trace,
I don't want to change the public API of the class - users of the class should be able to call all the methods in exactly the same way.
To make the question more concrete let's assume there are 3 classes:
public class Caller
{
public static void Call()
{
Traced traced = new Traced();
traced.Method1();
traced.Method2();
}
}
public class Traced
{
public void Method1(String name, Int32 value) { }
public void Method2(Object object) { }
}
public class Logger
{
public static void LogStart(MethodInfo method, Object[] parameterValues);
public static void LogEnd(MethodInfo method);
}
How do I invoke Logger.LogStart and Logger.LogEnd for every call to Method1 and Method2 without modifying the Caller.Call method and without adding the calls explicitly to Traced.Method1 and Traced.Method2?
Edit: What would be the solution if I'm allowed to slightly change the Call method?
C# is not an AOP oriented language. It has some AOP features and you can emulate some others but making AOP with C# is painful.
I looked up for ways to do exactly what you wanted to do and I found no easy way to do it.
As I understand it, this is what you want to do:
[Log()]
public void Method1(String name, Int32 value);
and in order to do that you have two main options
Inherit your class from MarshalByRefObject or ContextBoundObject and define an attribute which inherits from IMessageSink. This article has a good example. You have to consider nontheless that using a MarshalByRefObject the performance will go down like hell, and I mean it, I'm talking about a 10x performance lost so think carefully before trying that.
The other option is to inject code directly. In runtime, meaning you'll have to use reflection to "read" every class, get its attributes and inject the appropiate call (and for that matter I think you couldn't use the Reflection.Emit method as I think Reflection.Emit wouldn't allow you to insert new code inside an already existing method). At design time this will mean creating an extension to the CLR compiler which I have honestly no idea on how it's done.
The final option is using an IoC framework. Maybe it's not the perfect solution as most IoC frameworks works by defining entry points which allow methods to be hooked but, depending on what you want to achive, that might be a fair aproximation.
The simplest way to achieve that is probably to use PostSharp. It injects code inside your methods based on the attributes that you apply to it. It allows you to do exactly what you want.
Another option is to use the profiling API to inject code inside the method, but that is really hardcore.
You could achieve it with Interception feature of a DI container such as Castle Windsor. Indeed, it is possible to configure the container in such way that every classes that have a method decorated by a specific attribute would be intercepted.
Regarding point #3, OP asked for a solution without AOP framework. I assumed in the following answer that what should be avoided were Aspect, JointPoint, PointCut, etc. According to Interception documentation from CastleWindsor, none of those are required to accomplish what is asked.
Configure generic registration of an Interceptor, based on the presence of an attribute:
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;
}
}
Add the created IContributeComponentModelConstruction to container
container.Kernel.ComponentModelBuilder.AddContributor(new RequireInterception());
And you can do whatever you want in the interceptor itself
public class ConsoleLoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.Writeline("Log before executing");
invocation.Proceed();
Console.Writeline("Log after executing");
}
}
Add the logging attribute to your method to log
public class Traced
{
[Log]
public void Method1(String name, Int32 value) { }
[Log]
public void Method2(Object object) { }
}
Note that some handling of the attribute will be required if only some method of a class needs to be intercepted. By default, all public methods will be intercepted.
If you write a class - call it Tracing - that implements the IDisposable interface, you could wrap all method bodies in a
Using( Tracing tracing = new Tracing() ){ ... method body ...}
In the Tracing class you could the handle the logic of the traces in the constructor/Dispose method, respectively, in the Tracing class to keep track of the entering and exiting of the methods. Such that:
public class Traced
{
public void Method1(String name, Int32 value) {
using(Tracing tracer = new Tracing())
{
[... method body ...]
}
}
public void Method2(Object object) {
using(Tracing tracer = new Tracing())
{
[... method body ...]
}
}
}
If you want to trace after your methods without limitation (no code adaptation, no AOP Framework, no duplicate code), let me tell you, you need some magic...
Seriously, I resolved it to implement an AOP Framework working at runtime.
You can find here : NConcern .NET AOP Framework
I decided to create this AOP Framework to give a respond to this kind of needs. it is a simple library very lightweight. You can see an example of logger in home page.
If you don't want to use a 3rd party assembly, you can browse the code source (open source) and copy both files Aspect.Directory.cs and Aspect.Directory.Entry.cs to adapted as your wishes. Theses classes allow to replace your methods at runtime. I would just ask you to respect the license.
I hope you will find what you need or to convince you to finally use an AOP Framework.
Take a look at this - Pretty heavy stuff..
http://msdn.microsoft.com/en-us/magazine/cc164165.aspx
Essential .net - don box had a chapter on what you need called Interception.
I scraped some of it here (Sorry about the font colors - I had a dark theme back then...)
http://madcoderspeak.blogspot.com/2005/09/essential-interception-using-contexts.html
I have found a different way which may be easier...
Declare a Method InvokeMethod
[WebMethod]
public object InvokeMethod(string methodName, Dictionary<string, object> methodArguments)
{
try
{
string lowerMethodName = '_' + methodName.ToLowerInvariant();
List<object> tempParams = new List<object>();
foreach (MethodInfo methodInfo in serviceMethods.Where(methodInfo => methodInfo.Name.ToLowerInvariant() == lowerMethodName))
{
ParameterInfo[] parameters = methodInfo.GetParameters();
if (parameters.Length != methodArguments.Count()) continue;
else foreach (ParameterInfo parameter in parameters)
{
object argument = null;
if (methodArguments.TryGetValue(parameter.Name, out argument))
{
if (parameter.ParameterType.IsValueType)
{
System.ComponentModel.TypeConverter tc = System.ComponentModel.TypeDescriptor.GetConverter(parameter.ParameterType);
argument = tc.ConvertFrom(argument);
}
tempParams.Insert(parameter.Position, argument);
}
else goto ContinueLoop;
}
foreach (object attribute in methodInfo.GetCustomAttributes(true))
{
if (attribute is YourAttributeClass)
{
RequiresPermissionAttribute attrib = attribute as YourAttributeClass;
YourAttributeClass.YourMethod();//Mine throws an ex
}
}
return methodInfo.Invoke(this, tempParams.ToArray());
ContinueLoop:
continue;
}
return null;
}
catch
{
throw;
}
}
I then define my methods like so
[WebMethod]
public void BroadcastMessage(string Message)
{
//MessageBus.GetInstance().SendAll("<span class='system'>Web Service Broadcast: <b>" + Message + "</b></span>");
//return;
InvokeMethod("BroadcastMessage", new Dictionary<string, object>() { {"Message", Message} });
}
[RequiresPermission("editUser")]
void _BroadcastMessage(string Message)
{
MessageBus.GetInstance().SendAll("<span class='system'>Web Service Broadcast: <b>" + Message + "</b></span>");
return;
}
Now I can have the check at run time without the dependency injection...
No gotchas in site :)
Hopefully you will agree that this is less weight then a AOP Framework or deriving from MarshalByRefObject or using remoting or proxy classes.
First you have to modify your class to implement an interface (rather than implementing the MarshalByRefObject).
interface ITraced {
void Method1();
void Method2()
}
class Traced: ITraced { .... }
Next you need a generic wrapper object based on RealProxy to decorate any interface to allow intercepting any call to the decorated object.
class MethodLogInterceptor: RealProxy
{
public MethodLogInterceptor(Type interfaceType, object decorated)
: base(interfaceType)
{
_decorated = decorated;
}
public override IMessage Invoke(IMessage msg)
{
var methodCall = msg as IMethodCallMessage;
var methodInfo = methodCall.MethodBase;
Console.WriteLine("Precall " + methodInfo.Name);
var result = methodInfo.Invoke(_decorated, methodCall.InArgs);
Console.WriteLine("Postcall " + methodInfo.Name);
return new ReturnMessage(result, null, 0,
methodCall.LogicalCallContext, methodCall);
}
}
Now we are ready to intercept calls to Method1 and Method2 of ITraced
public class Caller
{
public static void Call()
{
ITraced traced = (ITraced)new MethodLogInterceptor(typeof(ITraced), new Traced()).GetTransparentProxy();
traced.Method1();
traced.Method2();
}
}
You can use open source framework CInject on CodePlex. You can write minimal code to create an Injector and get it to intercept any code quickly with CInject. Plus, since this is Open Source you can extend this as well.
Or you can follow the steps mentioned on this article on Intercepting Method Calls using IL and create your own interceptor using Reflection.Emit classes in C#.
I don't know a solution but my approach would be as follows.
Decorate the class (or its methods) with a custom attribute. Somewhere else in the program, let an initialization function reflect all types, read the methods decorated with the attributes and inject some IL code into the method. It might actually be more practical to replace the method by a stub that calls LogStart, the actual method and then LogEnd. Additionally, I don't know if you can change methods using reflection so it might be more practical to replace the whole type.
You could potentially use the GOF Decorator Pattern, and 'decorate' all classes that need tracing.
It's probably only really practical with an IOC container (but as pointer out earlier you may want to consider method interception if you're going to go down the IOC path).
you need to bug Ayende for an answer on how he did it:
http://ayende.com/Blog/archive/2009/11/19/can-you-hack-this-out.aspx
AOP is a must for clean code implementing, however if you want to surround a block in C#, generic methods have relatively easier usage. (with intelli sense and strongly typed code) Certainly, it can NOT be an alternative for AOP.
Although PostSHarp have little buggy issues (i do not feel confident for using at production), it is a good stuff.
Generic wrapper class,
public class Wrapper
{
public static Exception TryCatch(Action actionToWrap, Action<Exception> exceptionHandler = null)
{
Exception retval = null;
try
{
actionToWrap();
}
catch (Exception exception)
{
retval = exception;
if (exceptionHandler != null)
{
exceptionHandler(retval);
}
}
return retval;
}
public static Exception LogOnError(Action actionToWrap, string errorMessage = "", Action<Exception> afterExceptionHandled = null)
{
return Wrapper.TryCatch(actionToWrap, (e) =>
{
if (afterExceptionHandled != null)
{
afterExceptionHandled(e);
}
});
}
}
usage could be like this (with intelli sense of course)
var exception = Wrapper.LogOnError(() =>
{
MessageBox.Show("test");
throw new Exception("test");
}, "Hata");
Maybe it's to late for this answer but here it goes.
What you are looking to achieve is built in MediatR library.
This is my RequestLoggerBehaviour which intercepts all calls to my business layer.
namespace SmartWay.Application.Behaviours
{
public class RequestLoggerBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
private readonly ILogger _logger;
private readonly IAppSession _appSession;
private readonly ICreateLogGrain _createLogGrain;
public RequestLoggerBehaviour(ILogger<TRequest> logger, IAppSession appSession, IClusterClient clusterClient)
{
_logger = logger;
_appSession = appSession;
_createLogGrain = clusterClient.GetGrain<ICreateLogGrain>(Guid.NewGuid());
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var name = typeof(TRequest).Name;
_logger.LogInformation($"SmartWay request started: ClientId: {_appSession.ClientId} UserId: {_appSession.UserId} Operation: {name} Request: {request}");
var response = await next();
_logger.LogInformation($"SmartWay request ended: ClientId: {_appSession.ClientId} UserId: {_appSession.UserId} Operation: {name} Request: {request}");
return response;
}
}
}
You can also create performance behaviours to trace methods that take too long to execute for example.
Having clean architecture (MediatR) on your business layer will allow you to keep your code clean while you enforce SOLID principles.
You can see how it works here:
https://youtu.be/5OtUm1BLmG0?t=1
Write your own AOP library.
Use reflection to generate a logging proxy over your instances (not sure if you can do it without changing some part of your existing code).
Rewrite the assembly and inject your logging code (basically the same as 1).
Host the CLR and add logging at this level (i think this is the hardest solution to implement, not sure if you have the required hooks in the CLR though).
The best you can do before C# 6 with 'nameof' released is to use slow StackTrace and linq Expressions.
E.g. for such method
public void MyMethod(int age, string name)
{
log.DebugTrace(() => age, () => name);
//do your stuff
}
Such line may be produces in your log file
Method 'MyMethod' parameters age: 20 name: Mike
Here is the implementation:
//TODO: replace with 'nameof' in C# 6
public static void DebugTrace(this ILog log, params Expression<Func<object>>[] args)
{
#if DEBUG
var method = (new StackTrace()).GetFrame(1).GetMethod();
var parameters = new List<string>();
foreach(var arg in args)
{
MemberExpression memberExpression = null;
if (arg.Body is MemberExpression)
memberExpression = (MemberExpression)arg.Body;
if (arg.Body is UnaryExpression && ((UnaryExpression)arg.Body).Operand is MemberExpression)
memberExpression = (MemberExpression)((UnaryExpression)arg.Body).Operand;
parameters.Add(memberExpression == null ? "NA" : memberExpression.Member.Name + ": " + arg.Compile().DynamicInvoke().ToString());
}
log.Debug(string.Format("Method '{0}' parameters {1}", method.Name, string.Join(" ", parameters)));
#endif
}