What I am trying to achieve is to intercept the injection of a class, and call a specific method on the class to alter it's behaviour.
I have implemented the interceptor class that is given on the SimpleInjector website, and this is working, so I am able to get some functionality running when the class is intercepted.
My container is registering it as such:
container.InterceptWith<MyInterceptor>(type => type == typeof(IMyClass));
The class I am intercepting on looks as such:
public class MyClass : IMyClass
{
private IAnotherClass m_class;
public MyClass(IAnotherClass _class)
{
m_class = _class;
}
public void MethodToCall()
{
//changes properties on class
}
}
My interceptor class looks as such:
public class MyInterceptor : IInterceptor
{
private readonly ILogger logger;
public MyInterceptor(ILogger logger)
{
this.logger = logger;
}
public void Intercept(IInvocation invocation)
{
var watch = Stopwatch.StartNew();
// Calls the decorated instance.
invocation.Proceed();
var decoratedType = invocation.InvocationTarget.GetType();
logger.Trace(string.Format("{0} executed in {1} ms.",
decoratedType.Name, watch.ElapsedTicks));
}
}
What I am trying to achieve is to call a method on the intercepted IMyClass. So in the interceptor, call MyClass.MethodToCall()
I have tried to do something like this in the Intercept() method:
var classIntercepted = invocation.ReturnValue;
MethodInfo method = invocation.InvocationTarget.GetType().GetMethod("MethodToCall");
object magicValue = method.Invoke(classIntercepted, null);
But, the invocation.ReturnValue is not returning the MyClass instance, but rather the IAnotherClass instance
Why don't you use a decorator instead of using interception? This is often much easier, more maintainable and faster.
Here's an example:
public class PropSetMyClassDecorator : IMyClass
{
private MyClass decoratee;
public PropSetMyClassDecorator(MyClass decoratee) {
this.decoratee = decoratee;
}
public void MethodToCall() {
this.decoratee.SetConnectionString();
this.decoratee.MethodToCall();
}
}
You can register this decorator as follows:
container.Register<IMyClass, PropSetMyClassDecorator>();
Do note that instead of registering MyClass, we only register the decorator. Since the decorator directly depends on MyClass (not on the interface) MyClass will be automatically resolved by Simple Injector.
Yet another option is to register an initializer as follows:
container.RegisterInitializer<MyClass>(instance => {
instance.SetConnectionString();
});
The initializer delegate will be called every time after a MyClass instance is constructed. The behavior is a bit different in this case, since the method isn't called every time, but only during construction. Usually however, this should be sufficient, since you should normally not change a service during runtime, since you are complicating things.
Ok, found a solution fairly shortly after posting the question.
I changed my Intercept function to be the following:
public void Intercept(IInvocation invocation)
{
// Calls the decorated instance.
invocation.Proceed();
var classIntercepted = invocation.InvocationTarget;
MethodInfo method = invocation.InvocationTarget.GetType().GetMethod("SetConnectionString");
method.Invoke(classIntercepted, null);
}
Related
In my implementation, I need to dynamically resolve a service, based on the servicekey. Therefor, I want to pass a Func, but can't get that working. Any help on this is appreciated.
Let's have the following implemention:
public interface IMyInterface {
void Foo();
}
public class ClassA : IMyInterface {
void Foo() => BarA();
}
public class ClassB : IMyInterface {
void Foo() => BarB();
}
public class ClassC : IOtherInterface {
private readonly Func<string, IMyInterface> getInstance_;
void ClassC(Func<string, IMyInterface> getInstance)
{
getInstance_ = getInstance;
}
void SomeLogic()
{
IMyInterface implementation = getInstance("keyA");
implementation.Foo();
}
}
public static void Main()
{
var c = new Container();
c.Register<IMyInterface, ClassA>(serviceKey:"keyA");
c.Register<IMyInterface, ClassB>(serviceKey:"keyB");
c.Register<IOtherInterface, ClassC>();
c.Resolve<IOtherInterface>();
}
The last call fails, which I understand. The exception thrown is:
DryIoc.ContainerException: 'Unable to resolve IMyInterface with passed arguments [_String0] IsWrappedInFunc, IsDirectlyWrappedInFunc
in wrapper Func<String, IMyInterface> FactoryId=10 with passed arguments [_String0] IsResolutionCall
from Container with Scope {no name}
with Rules with {TrackingDisposableTransients} and without {ThrowOnRegisteringDisposableTransient}
with normal and dynamic registrations:
("keyA", {FactoryID=32, ImplType=ClassA}) ("keyB", {FactoryID=33, ImplType=ClassB}) '
I figured out how to register this with a Delegate:
c.RegisterDelegate<Func<string, IMyInterface>>(r => (key) => c.Resolve<IMyInterface>(key));
But in the documentation, DryIoc recommends using factory-methods above Delegates.
I've played a lot with Made.Of-notations (which I find poorly documented), but have not found a working one.
Is this possible with a (static) Factory-method?
If you need to dynamically select the service based on the key but without relying on Service Locator anti-pattern (without injecting the IResolver into ClassC) -
you may inject all available service factories as described here https://github.com/dadhi/DryIoc/blob/master/docs/DryIoc.Docs/RegisterResolve.md#keyed-registrations in the second example:
public class ClassC : IOtherInterface {
private readonly Func<string, IMyInterface> _implementations;
void ClassC(KeyValuePair<string, Func<IMyInterface>>[] implementations)
{
_implementations = implementations;
}
void SomeLogic()
{
var implementationFactory = _implementations.First(x => x.Key == "keyA").Value;
var implementation = implementationFactory();
implementation.Foo();
}
}
BTW, The same approach is taken in Autofac and maybe by other DI containers capable to compose the wrappers like Func, Lazy and the collections.
BTW2, If you don't like the KeyValuePair you may use Tuple instead.
I am new at using Autofac, so apologies if this is a stupid question.
Let's say I have an abstract class FooBase with parameterless constructor, and an implementation thereof called Foo.
In my AP.Net MVC5 client code, I would like to be able to create an instance of an object of type FooBase (I have set up Autofac to resolve it to Foo). The lifetime and scope of this instance is limited to my method, and I would like to do it in a fashion similar to calling a factory method if possible.
Currently I am making use of the DependencyResolver, but it seems a bit contrived. Is there a simpler way to do this?
For example, here is what it currently looks like...
public void SendMessage()
{
var foo = DependencyResolver.Current.GetService<FooBase>();
Debug.WriteLine(foo.Name);
}
I am looking for something a little more like this...
public void SendMessage()
{
var foo = IoC.Resolve<FooBase>();
Debug.WriteLine(foo.Name);
}
I think you can use delegate factories
First declare the delegate factory in the type that you want to build at runtime:
public class TestService
{
public delegate TestService Factory();
//other methods....
}
Then you can inject the factory as any other dependency, ex:
public class ExampleController
{
private TestService.Factory _factory;
public ExampleController(TestService.Factory factory)
{
_factory = factory;
}
public OtherMethod()
{
var serviceInstance = _factory();
}
}
Hope this helps!
Instead of using the Service Locator which is an anti-pattern, you can simply inject a factory which allows you to create an instance of the dependency if/when you want. The simplest way is to inject a Func<FooBase>. Autofac supports this natively. If you just register FooBase, AutoFac knows how to inject Func<FooBase>. Here is an example:
public class TestClass
{
private Func<FooBase> m_FooBaseFactory;
public TestClass(Func<FooBase> factory)
{
m_FooBaseFactory = factory;
}
public void TestMethod()
{
var foo = m_FooBaseFactory();
//consume foo here
}
}
Here is my Module:
public class LoggerModule : NinjectModule
{
public override void Load()
{
Bind<ILogger>().To<NLogLogger>()
.WithConstructorArgument(
typeof(Type),
x => x.Request.ParentContext.Plan.Type);
}
}
So as you can see the NLogLogger is expecting the Type to be passed into the constructor.
This is my Unit Test:
[Test]
public void ResolveLoggerDependency()
{
var module = new LoggerModule();
var kernal = new StandardKernel(module);
var service = kernal.Get<ILogger>(new ConstructorArgument("type", typeof(int)));
Assert.That(service, Is.Not.Null);
}
It is throwing a null reference error on the kernal.Get<ILogger> so I can only assume I am not passing the constructor value correctly. How can I pass in a Type when using Get<T>?
So, this question as it seems relates to your other question.
The requirement in that question was to inject into NLogLogger the type of the object into which the it will be injected.
The registration in this case is assuming that this interface ILogger will not be resolved outside the context of a parent class into which it will be injected. And you are getting the exception because there is no parent class context when you directly attempt to resolve the ILogger interface.
I am assuming that in your unit test, your would like to test that this registration actually work. I would suggest the following:
First, create a class the you will use in your tests:
public class TestClass
{
private readonly ILogger m_Logger;
public TestClass(ILogger logger)
{
m_Logger = logger;
}
public ILogger Logger
{
get { return m_Logger; }
}
}
And then use such class in your unit tests like this:
[Test]
public void ResolveLoggerDependency()
{
var module = new LoggerModule();
var kernal = new StandardKernel(module);
var test_object = kernal.Get<TestClass>();
Assert.That(test_object.Logger, Is.Not.Null);
}
You can further verify that the NLogLogger actually used the TestClass class's name to construct the NLog logger. This might require the use of Reflection though, I am not sure.
In your Load method you can just set it up using Bind<ILogger>().To<NLogLogger>();
Follow up to an older question here. Say I have a registration like the following:
container.Register(typeof(IHandleCommand<>), _handlerAssemblies, Lifestyle.Transient);
container.RegisterDecorator(typeof(IHandleCommand<>),
typeof(MetricsCommandHandlerWrapper<>), Lifestyle.Singleton);
Where the MetricsCommandHandlerWrapper is defined like so:
public class MetricsCommandHandlerWrapper<T> : IHandleCommand<T> where T: ICommand
{
private readonly ICollectMetrics _metrics;
private readonly Func<IHandleCommand<T>> _handlerFactory;
public MetricsCommandHandlerWrapper(ICollectMetrics metrics,
Func<IHandleCommand<T>> handlerFactory)
{
_metrics = metrics;
_handlerFactory = handlerFactory;
}
public async Task HandleAsync(T command)
{
// code to record metrics around command handling which eventually invokes
await _handlerFactory().HandleAsync(command).ConfigureAwait(false);
}
}
How can I write a unit test that asserts the actual decoratee handlers are registered with Transient lifestyle?
I have tried composing the root and inspecting the registration for a closed IHandleCommand<FakeCommand> type, which reveals an ImplementationType of MetricsCommandHandlerWrapper<FakeCommand> as expected. Invoking GetRelationships() on that registration reveals its 2 dependencies, ICollectMetrics and the one I am interested in, the Func<IHandleCommand<FakeCommand>> factory delegate, which is registered as a Singleton. However invoking .Dependency.GetInstance() on that factory delegate throws an exception that the instance producer returned null.
Is there any way to assert that the inner decoratee is registered as Transient, and if so, how?
The use of the Func<T> delays the building of the object graph, and from perspective of the diagnostic system, the graphs stops at that point. So, it's not possible to do this analysis.
Instead of completely relying on Simple Injector's internals however, you can also choose to make some minor changing in your application to allow testing decorators.
What you can do is implement an IDecorator abstraction on your decorators:
public interface IDecorator {
object Decoratee { get; }
}
Now each decorator can implement this interface. For the MetricsCommandHandlerWrapper<T>, it might look as follows:
public class MetricsCommandHandlerWrapper<T> : IHandleCommand<T>, IDecorator where T: ICommand
{
private readonly ICollectMetrics _metrics;
private readonly Func<IHandleCommand<T>> _handlerFactory;
public MetricsCommandHandlerWrapper(ICollectMetrics metrics,
Func<IHandleCommand<T>> handlerFactory) {
_metrics = metrics;
_handlerFactory = handlerFactory;
}
public object Decoratee { get { return _handlerFactory(); }
public async Task HandleAsync(T command) { ... }
}
On top of the IDecorator interface, you can define a simple extension method:
public static IEnumerable<Type> GetDecoratorChain(this IDecorator decorator) {
while (decorator != null) {
yield return decorator.GetType();
decorator = decorator.Decoratee as IDecorator;
}
}
Inside your unit test you can now resolve a handler and ask for the list of applied decorators. Using this list you can verify whether decorators are applied in the correct order.
My factory is using method injection because I thought this was the best way to make it so far. Besides, I doubt it is a good thing after having to call on its Create method from within a dependent object.
The only way I might think of whilst continuing to use the parameterized factory Create method, is to inject the dependencies directly in the MainPresenter so that it may provide with the dependencies to the method, and I dislike it. It dislike it because it is not the MainPresenter that depends on the ICustomerManagementView and the ICustomerDetailPresenterFactory, it's its dependency. So I would feel like I'm sabotaging my own code by doing so.
MainPresenter
public class MainPresenter : Presenter<IMainView>, IMainViewUiHandler {
public MainPresenter(IMainView view
, ICustomerManagementPresenterFactory customerManagementFactory)
: base(view) {
this.customerManagementPresenterFactory = customerManagementPresenterFactory;
}
public void ManageCustomers() {
// The following line is causing trouble.
// As you can see per the ICustomerManagementPresenterFactory code sample,
// the Create() method takes two parameters:
// 1. ICustomerManagementView, and
// 2. ICustomerDetailPresenterFactory
// Hence I have to provide the dependencies manually, I guess. Which is
// something to avoid at any cost.
var customerManagementPresenter = customerManagementPresenterFactory.Create();
customerManagementPresenter.ShowView();
}
}
ICustomerManagementPresenterFactory
public interface ICustomerManagementPresenterFactory {
// Here. Though I ask Ninject to inject my dependencies, I need to
// provide values to the parameters when calling the method from within
// the MainPresenter class. The compiler won't let me do otherwise! And
// this makes sense!...
[Inject]
CustomerManagementPresenter Create(ICustomerManagementView view
, ICustomerDetailPresenterFactory factory);
}
IMainView
public interface IMainView : IView, IHasUiHandler<IMainViewUiHandler> {
}
IMainViewUiHandler
public interface IMainViewUiHandler : IUiHandler {
void ManageCustomers();
}
IUiHandler
public interface IUiHandler {
}
IHasUiHandler
public interface IHasUiHandler<H> where H : IUiHandler {
H Handler { set; }
}
MainForm
public partial class MainForm : Form, IMainView {
public MainForm() { InitializeComponent(); }
public IMainViewUiHandler Handler { private get { return handler; } set { setHandler(value); } }
}
CompositionRoot
public class CompositionRoot {
private CompositionRoot() { }
public static IKernel BuildObjectGraph() {
IKernel kernel = new StandardKernel();
BindFactories(kernel);
BindViews(kernel);
}
private static void BindFactories(IKernel kernel) {
kernel.Bind(services => services
.From(AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => !a.FullName.Contains("Tests")))
.SelectAllInterfaces()
.EndingWith("Factory")
.BindToFactory()
);
}
private static void BindViews(IKernel kernel) {
kernel.Bind(services => services
.From(AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => a.FullName.Contains("Windows")
&& !a.FullName.Contains("Tests"))
.SelectAllClasses()
.EndingWith("Form")
.BindSelection((type, baseType) => type
.GetInterfaces()
.Where(iface => iface.Name.EndsWith("View"))
)
);
}
}
So I wonder, is it best to implement the ICustomerManagementPresenterFactory and bind the implementer with it within my CompositionRoot, so that I could provide those dependencies through constructor injection to the Create method which shall no longer take any arguments, or shall I make it otherwise?
What I like of writing a simple interface is that Ninject does it all for me to a factory, and no code is necessary to build an instance of the desired type. Besides, when the constructor of the class to be created uses constructor injection, it seems like it is impossible to have a simple factory interface bound as a factory, and one need to implement the factory interface by hand.
What did I get right/wrong?
As a matter of fact you don't need to pass parameters to the factory Create method at all - except in case they are parameters which need to be passed "down" because they cannot be bound in the composition root (for example an input value). However, passing such parameters to constructors is usually a code smell. Mostly, it's a better idea to pass these parameters to methods instead of constructors (for example: Adder.Add(5,3);, not new Adder(5, 3).ComputeResult();.
Now consider the following example, which works perfectly fine:
public class Dependency1 { }
public interface IDependency2 { }
public class Dependency2 : IDependency2 { }
public interface IBar { }
public class Bar : IBar
{
public Bar(Dependency1 d1, IDependency2 d2) { }
}
public interface IBarFactory
{
IBar Create();
}
var kernel = new StandardKernel();
kernel.Bind<IBarFactory>().ToFactory();
kernel.Bind<IBar>().To<Bar>();
kernel.Bind<Dependency1>().ToSelf();
kernel.Bind<IDependency2>().To<Dependency2>();
var factory = kernel.Get<IBarFactory>();
var bar = factory.Create();
bar.Should().BeOfType<Bar>();
even though Bar takes two constructor arguments, the generated IBarFactory's Create() method does not specify so. No problem, ninject will resolve it automatically.
Now let me give you an example what .ToFactory() actually results in. Consider the factory:
public interface ISomeFactory
{
ISomething Create(string parameter1);
}
Will result in (remark: it's realised by interceptors and not by weaving it, so the example is a simplificiation):
public class SomeFactory : ISomeFactory
{
private readonly IResolutionRoot resolutionRoot;
public SomeFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public ISomething Create(string parameter1)
{
this.resolutionRoot.Get<ISomething>(new ConstructorArgument("parameter1", parameter1);
}
}
The ConstructorArgument tells ninject to pass the value of parameter1 to the ctor-parameter named "parameter".
All other parameters are resolved "as usual". If a constructor parameter cannot be resolved (neither passed as parameter nor bound) ninject will throw an exception stating that the parameter cannot be resolved.