Aspect Orienting Logging / Interception Using Structure Map - c#

I am using Structure Map as my DI container and I would like to use this to setup some aspect oriented logging. (I am using version 4.7.0)
Using RealProxy I have created a 'DynamicProxy' class to intercept methods before and after they are executed and perform logging (in the example this is just writing to the console).
Logging class:
public class DynamicProxy<T> : RealProxy
{
private readonly T _decorated;
public DynamicProxy(T decorated)
: base(typeof(T)) =>
this._decorated = decorated;
private void Log(string msg, object arg = null)
{
Console.WriteLine(msg, arg);
}
public override IMessage Invoke(IMessage msg)
{
var methodCall = msg as IMethodCallMessage;
var methodInfo = methodCall.MethodBase as MethodInfo;
var inputMessage = new StringBuilder();
inputMessage.Append($"Before execution of: '{methodCall.MethodName}' ");
for (int i = 0; i < methodCall.ArgCount; i++)
inputMessage.Append($"Arg: '{methodCall.GetArgName(i)}' value = '{methodCall.GetArg(i)}'");
Log(inputMessage.ToString());
try
{
var result = methodInfo.Invoke(this._decorated, methodCall.InArgs);
var returnValue = methodInfo.ReturnType == typeof(void) ? "void" : result.ToString();
Log($"After execution of '{methodCall.MethodName}'. Return value was '{returnValue}'");
return new ReturnMessage(result, null, 0,
methodCall.LogicalCallContext, methodCall);
}
catch (Exception e)
{
Log(string.Format(
"In Dynamic Proxy- Exception {0} executing '{1}'", e),
methodCall.MethodName);
return new ReturnMessage(e, methodCall);
}
}
I have then created a helper method to create concrete implementations of interfaces wrappered in the Dynamic proxy:
public class Factory
{
public static InterfaceType CreateDynamic<InterfaceType, ConcreteType>(params object[] args) where ConcreteType : InterfaceType
{
var decorated = (ConcreteType) Activator.CreateInstance(typeof(ConcreteType), args);
var dynamic = new DynamicProxy<InterfaceType>(decorated);
return (InterfaceType) dynamic.GetTransparentProxy();
}
}
Using StructureMap I can then setup my container to return instances wrappered in my Proxy. For example I have the following working as expected:
This is the interface / implementation I have used to experiment with:
public interface IDoSomething
{
void Work1(string additional);
double Work2();
}
public class DoSomething : IDoSomething
{
private string message;
public DoSomething(string message)
{
this.message = message;
}
public void Work1(string additional)
{
Console.WriteLine("Method Work 1 :{0} {1}", this.message, additional);
}
public double Work2()
{
Console.WriteLine("Method Work 2 Makes Pi :{0}", this.message);
return Math.PI;
}
}
And this is my Program
class Program
{
static void Main(string[] args)
{
Console.WriteLine("DoSomething with proxy, created through DI:");
var container = new Container(_ =>
{
_.For<IDoSomething>().Use(x => Factory.CreateDynamic<IDoSomething, DoSomething>("message from DI"));
});
Console.WriteLine();
Console.WriteLine();
var somethingElse = container.GetInstance<IDoSomething>();
somethingElse.Work1("Hello");
Console.ReadLine();
}
}
It outputs as expected, showing me the messages from the proxy class and the message passed in on the constructor
However, there are some limitations to this approach that I am having trouble overcoming:
How do I setup my container so that every interface is created wrappered in the proxy?
This implementation fails when the concrete implementation itself requires an interface, so is there way of integrating this into StructureMap? I have seen this done with SimpleInjector (https://simpleinjector.readthedocs.io/en/latest/aop.html#interception) but I have not been able to see how this is done in StructureMap, but I imagine there must be a way of making this happen. Maybe using reflection and recursion? (I cannot use SimpleInjector because of its reliance on a single constructor and PostSharp is expensive).

Related

Castle Windsor Interceptor

I'm trying to use the code from this page, http://docs.castleproject.org/Windsor.Introduction-to-AOP-With-Castle.ashx and register an interceptor in a fluent manner.
But I get this error thrown. I've tried Castle Windsor versions from 2.5 to 3.3. So it must be something very basic in how interceptors are set up
Classes
public interface ISomething
{
Int32 Augment(Int32 input);
void DoSomething(String input);
Int32 Property { get; set; }
}
class Something : ISomething
{
public int Augment(int input) {
return input + 1;
}
public void DoSomething(string input) {
Console.WriteLine("I'm doing something: " + input);
}
public int Property { get; set; }
}
public class DumpInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation) {
Console.WriteLine("DumpInterceptorCalled on method " +
invocation.Method.Name);
invocation.Proceed();
if (invocation.Method.ReturnType == typeof(Int32)) {
invocation.ReturnValue = (Int32)invocation.ReturnValue + 1;
}
Console.WriteLine("DumpInterceptor returnvalue is " +
(invocation.ReturnValue ?? "NULL"));
}
}
Setup
Console.WriteLine("Run 2 - configuration fluent");
using (WindsorContainer container = new WindsorContainer())
{
container.Register(
Component.For<IInterceptor>()
.ImplementedBy<DumpInterceptor>()
.Named("myinterceptor"));
container.Register(
Component.For<ISomething>()
.ImplementedBy<Something>()
.Interceptors(InterceptorReference.ForKey("myinterceptor")).Anywhere);
ISomething something = container.Resolve<ISomething>(); //Offending row
something.DoSomething("");
Console.WriteLine("Augment 10 returns " + something.Augment(10));
}
Error
Type 'Castle.Proxies.ISomethingProxy' from
assembly'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null' is attempting to implement an inaccessible
interface.
The answer
So I found why this was happening. Appearantly if you create inner classes and interfaces you can register and resolve them but attaching interceptors to them won't work
Example - where the error will be triggered
class Program
{
public static void Main(String [] args)
{
var container = new WindsorContainer();
container.Register(Component.For<TestInterceptor>().Named("test"));
container.Register(Component.For<InnerInterface>().ImplementedBy<InnerClass>().Interceptors(InterceptorReference.ForKey("test")).Anywhere);
// this row below will throw the exception
var innerClassInstance = container.Resolve<InnerInterface>();
}
class InnerClass : InnerInterface { }
interface InnerInterface { }
class TestInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
throw new NotImplementedException();
}
}
}
Conclusion
So to conclude my intention was not to create inner classes in the first place but rather put together a demo to showcase Castle Windsor. But maybe this can help someone if they run into the same error as me..

Combine multiple interfaces into one at runtime in C#

I need to combine multiple interfaces a runtime to create a new type. For example I might have the following interfaces:
public interface IA{
}
public interface IB{
}
At runtime I want to be able to generate another interface so that in the following sudo code works:
Type newInterface = generator.Combine(typeof(IA), typeof(IB));
var instance = generator.CreateInstance(newInterface);
Assert.IsTrue(instance is IA);
Assert.IsTrue(instance is IB);
Is there a way to do this in .Net C#?
It is possible because of power of Castle Dynamic Proxy
public interface A
{
void DoA();
}
public interface B
{
void DoB();
}
public class IInterceptorX : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine(invocation.Method.Name + " is beign invoked");
}
}
class Program
{
static void Main(string[] args)
{
var generator = new ProxyGenerator();
dynamic newObject = generator.CreateInterfaceProxyWithoutTarget(typeof(A), new Type[] { typeof(B) }, new IInterceptorX());
Console.WriteLine(newObject is A); // True
Console.WriteLine(newObject is B); // True
newObject.DoA(); // DoA is being invoked
}
}

Castle DynamicProxy - 'classToProxy' must be a class

I am probably missing something extremely simple.
I am just trying to write a very minimalistic example of usage of DynamicProxy - I basically want to intercept the call and display method name and parameter value. I have code as follows:
public class FirstKindInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("First kind interceptor before {0} call with parameter {1} ", invocation.Method.Name, invocation.Arguments[0]);
invocation.Proceed();
Console.WriteLine("First kind interceptor after the call");
}
}
public interface IFancyService
{
string GetResponse(string request);
}
public class FancyService : IFancyService
{
public string GetResponse(string request)
{
return "Did you just say '" + request + "'?";
}
}
class Program
{
static void Main(string[] args)
{
var service = new FancyService();
var interceptor = new FirstKindInterceptor();
var generator = new ProxyGenerator();
var proxy = generator.CreateClassProxyWithTarget<IFancyService>(service, new IInterceptor[] { interceptor } );
Console.WriteLine(proxy.GetResponse("what?"));
}
}
However, when I run it I get a following exception:
Unhandled Exception: System.ArgumentException: 'classToProxy' must be
a class Parameter name: classToProxy
What am I missing?
The error is that CreateClassProxyWithTarget needs to be a type of class not interface. CreateInterfaceProxyWithTarget uses an interface.

Strongly typed way of storing type references

I need to store a collection of types.
All types implement the same interface IHandler<T>, where T is a parameter of the parent class.
At runtime, I enumerate the list of handlers and process a message. Each handler is created by a builder (just uses StructureMap internally). The builder exposes a method like:
static void DoSomething<T>(Action<T> action)
{
}
Of course, I only have a Type so can't use the above.
I've got round this by also passing the underlying interface as the generic parameter and the concrete type as a parameter:
DoSomething<IHandler<T>>(handlerType, h =>
{
h.Handle(message);
});
Then inside DoSomething I can get an instance of handlerType but cast it as IHandler<T>.
Just wondered if there was a better/cleaner way.
Update
In response to some of the comments.
The collection is an ICollection<Type>, not instances. The message handlers are created on demand, on different threads, for each batch of messages, so creating the handlers in advance, or using Lazy<T>, was not an option.
Essentially I am trying to abstract away some direct references to StructureMap. Specifically, DoSomething<T> actually creates the handler using a nested container, before executing the action (it's Handle method).
Update 2 (solution)
I realized that I could handle (no pun intended) this better by storing a collection of Action<T> and creating the handlers using a factory. Here's a simple example:
public class SimpleProcessor<T> where T : IMessage
{
ICollection<Action<T>> handlers;
T message;
public SimpleProcessor(T message)
{
this.handlers = new List<Action<T>>();
this.message = message;
}
public void AddHandler(Action<T> handler)
{
handlers.Add(handler);
}
public void Process()
{
foreach (var handler in handlers)
{
handler(message);
}
}
}
Usage:
var testMessage = new TestMessage { Message = "Foo" };
var simpleProcessor = new SimpleProcessor<TestMessage>(testMessage);
simpleProcessor.AddHandler(m => DoSomething<TestMessageHandler>(h => h.Handle(m)));
simpleProcessor.Process();
I'm more or less happy with this solution.
If you're willing to change Action<T> into Action<dynamic>, then you can do something like this:
class Program
{
static void Main(string[] args)
{
try
{
var myMessage = new object();
Action<dynamic> action = (dynamic h) => { h.Handle(myMessage); };
Type myType = typeof(int);
var method = typeof(Program).GetMethod("DoSomething");
var concreteMethod = method.MakeGenericMethod(myType);
concreteMethod.Invoke(null, new [] { action });
Console.ReadKey();
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
Console.ReadKey();
}
}
static public void DoSomething<T>(Action<dynamic> action)
{
Console.WriteLine("DoSomething invoked with T = " + typeof(T).FullName);
}
}

MOQ - How to verify static class call and delegates?

I just started reading on Moq framework and thought of applying it to my existing code. I could come up with a test case to verify basic function calls. But now stuck at applying it to delegates and static classes.
Below is the system under test (SUT)
public class SUT : ISUT
{
private IInterface1 i1;,
private IInterface2 i2;
public SUT(IInterface1 i1, IInterface2 i2)
{
this.i1 = i1;
this.i2 = i2;
}
public void FunctionToTest(Action<string> someDelegate, Action otherDelegate)
{
var list = i2.GetList();
foreach(var r in list)
{
i1.SomeFunction(r);
if(someDelegate != null)
someDelegate("message");
SomeHelper.LogData(r);
}
if(otherDelegate != null)
otherDelegate();
}
}
I have setup my test as below
[TestFixture]
public class when_list_contains_atleast_one_item
{
ISUT sut;
Mock<IInterface1> mockI1;
Mock<IInterface2> mockI2;
public SUT_Tester()
{
mockI1 = new Mock<IInterface1>();
mockI2 = new Mock<IInterface2>();
sut = new SUT(mockI1.Object, mockI2.Object);
}
[Test]
public void it_should_call_somefunction_calldelegates_and_log_data()
{
var dummyList = new List<string> { "string1", "string2" };
mockI2.Setup(m2 => m2.GetList()).Returns(dummyList).Verifiable();
sut.FunctionToTest(It.IsAny<Action<string>>(), It.IsAny<Action>());
// How to verify delegates were raised
// How to verify SomeHelper.LogData was called
mockI1.Verify(m => m.SomeFunction(It.IsAny<string>()), Times.Exactly(2));
mockI2.Verify();
}
}
How to verify that someDelegate and otherDelegate were raised ?
SomeHelper is a static class and LogData is a static function. How to verify that LogData was called?
Below is the SomeHelper class
public static class SomeHelper
{
static ILogger logger = LoggerManager.GetLogger("Something");
public static void LogData(string input)
{
logger.Info(input);
}
}
You cannot verify static methods since they cannot be mocked by Moq.
In order to verify calls on the delegates, create them so that they call a local function and you keep the state and verify:
string localString = string.Empty;
Action<string> action = (string s) => localString = s;
// ... pass it to the test
Assert.(localString == "TheStringItMustbe");
(UPDATE)
OK to check an action that has no in params, increment a local variable and assert if it has been incremented (or something similar):
int localVar = 0;
Action action = () => localVar++;
// ... pass it to the test
Assert.(localVar == 1);
You might want to consider changing the IInterface1/2 interfaces so that they either take an ILogger as a parameter into SomeFunction, or have a settable ILogger property.
Then you could pass a mocked ILogger into SomeFunction.

Categories

Resources