Using Ninject as IoC for EasyNetQ - ninject

i'm using EasyNetQ library in my project and I would like to use Ninject as IoC Container for EasyNetQ components.
I created a custom logger in order to log anythong from EasyNetQ:
public class LogNothingLogger : IEasyNetQLogger
{
...
}
And then using the Ninject extension in my main function:
public class Program
{
static void Main(string[] args)
{
// Container creation and custom logger registration
IKernel cointainer = new StandardKernel();
cointainer.Bind<IEasyNetQLogger>().To<LogNothingLogger>();
// Register Ninject as IoC Container for EasyNetQ
cointainer.RegisterAsEasyNetQContainerFactory();
// Create bus
using (IBus bus = RabbitHutch.CreateBus("host=localhost"))
{
// Do something with bus...
}
}
}
But I get the following exception:
Ninject.ActivationException was unhandled
More than one matching bindings are available.
Matching bindings:
1) binding from IEasyNetQLogger to LogNothingLogger
2) binding from IEasyNetQLogger to method
Activation path:
2) Injection of dependency IEasyNetQLogger into parameter logger of constructor of type RabbitBus
1) Request for RabbitBus
Suggestions:
1) Ensure that you have defined a binding for IEasyNetQLogger only once.
[...]
Am I using this package in the wrong way? Is there any solution?
Thanks!

As the exception says, there are two bindings for IEasyNetQLogger.
I suppose that an ninject extension you are using is already binding an IEasyNetQLogger.
You could use Rebind (IBindingRoot.Rebind<IEasyNetQLogger>()) to override any existing binding for IEasyNetQLogger.
But i would also advise you to look into why the extension is already creating a binding and how it is supposed to be used.
What is the extension you are using?
Edit: i took a glance at https://github.com/mikehadlow/EasyNetQ/tree/master/Source/EasyNetQ.DI.Ninject
and i did not find any binding for IEasyNetQLogger. Are you sure you don't have defined an additional IBindingRoot.Bind<IEasyNetQLogger>().ToMethod(...) binding?
It could also be NinjectAdapter.Register<IEasyNetQLogger>(Func<IEasyNetQLogger> ...).
If you have not done so, then the EasyNetQ is already registering a logger by NinjectAdapter.Register<IEasyNetQLogger>(Func<IEasyNetQLogger> ...).
As before, you can use Rebind(..) to replace the binding (which must be done after the original binding was created!) or look into how it is supposed to work.
Of course you might also just want to skip the binding since you only created one for "log nothing logger"...

Related

What is NInjects equivalent of TryAdd

In other DI containers, I have observed TryAddScoped, TryAddTransient, TryAddSingleton etc.
The idea behind Try is to avoid registering multiple times. If a service is already registered, then using Try will not attempt to register again I guess.
With inject
Kernel.Bind<IHttpContextAccessor>().To<HttpContextAccessor>().InSingletonScope();
So is there any Try equivalent in Ninject?
There's no simple equivalent.
Performing
Kernel.Bind<IHttpContextAccessor>().To<HttpContextAccessor>().InSingletonScope();
Kernel.Bind<IHttpContextAccessor>().To<HttpContextAccessor>().InSingletonScope();
will result in in an exception when resolving a IHttpContextAccessor, and when resolving IEnumerable<IHttpContextAccessor> it will return two HttpContextAccessor instances.
However, you can write your own "Try":
Checking whether Binding already exists
if(!Kernel.GetBindings(typeof(IHttpContextAccessor)).Any())
{
Kernel.Bind<IHttpContextAccessor>().To<HttpContextAccessor>().InSingletonScope();
}
Of course you can also write your own extension method for that:
public static class NinjectBindingExtensions
{
public static void TryBind<T>(
this IKernel kernel,
Action<IBindingToSyntax<T>> configureBinding)
{
if (!kernel.GetBindings(typeof(T)).Any())
{
configureBinding(kernel.Bind<T>());
}
}
}
Rebind
One way to work around the issue is to use .Rebind instead of .Bind. If there's no pre-existing binding it will work just like .Bind. And if there's a pre-existing binding, it will replace it. Thus:
Kernel.Rebind<IHttpContextAccessor>().To<HttpContextAccessor>().InSingletonScope();
Kernel.Rebind<IHttpContextAccessor>().To<HttpContextAccessor>().InSingletonScope();
Resolving IHttpContextAccessor will result in one instance of HttpContextAccessor.
Preventing Duplicate Module Loading
In case the problem is not with multiple components / NinjectModules creating bindings for the same type, but rather with loading the same NinjectModule twice, you can can prevent duplicate loading by:
if(!Kernel.HasModule(typeof(MyModule)))
{
Kernel.Load<MyModule>();
}

Container.GetInstance(Type) when using WcfOperationLifestyle throws ActivationException

I have a WebAPI service using SimpleInjector. I have this set up using AsyncScopedLifestyle for my scoped dependencies, and one of these dependencies is my Entity Framework DataContext. Many things in my service depend on the DataContext, and it is generally injected in to my MediatR handlers using constructor injection - this works well. Separately I have a few areas where I need to create an instance of an object given its type (as a string), so I have created a custom activator class (ResolvingActivator) that is configured with a reference to Container.GetInstance(Type):
In my container bootstrap code:
ResolvingActivator.Configure(container.GetInstance);
I can then create objects by using methods such as:
ResolvingActivator.CreateInstance<T>(typeName)
When I'm using WebAPI, the above is working perfectly.
A further part of the project is a legacy API that uses WCF. I have implemented this as a translation layer, where I translate old message formats to new message formats and then dispatch the messages to the Mediator; I then translate the responses (in new format) back to old format and return those to the caller. Because I need access to the Mediator in my WCF services, I'm injecting this in their constructors, and using the SimpleInjector.Integration.Wcf package to let SimpleInjector's supplied SimpleInjectorServiceHostFactory build instances of the services. I've also created a hybrid lifestyle, so I can use the same container for my both my WebAPI and WCF services:
container.Options.DefaultScopedLifestyle = Lifestyle.CreateHybrid(
new AsyncScopedLifestyle(),
new WcfOperationLifestyle());
This works well for some calls, but when a call ultimately calls my ResolvingActivator class, I get an ActivationException thrown, with the following message:
The DataContext is registered as 'Hybrid Async Scoped / WCF Operation' lifestyle, but the instance is requested outside the context of an active (Hybrid Async Scoped / WCF Operation) scope.
As I only receive this error when making WCF calls, I'm wondering if I have something wrong in my configuration. In a nutshell, this will work:
public class SomeClass
{
private readonly DataContext db;
public SomeClass(DataContext db)
{
this.db = db;
}
public bool SomeMethod() => this.db.Table.Any();
}
But this will not:
public class SomeClass
{
public bool SomeMethod()
{
// Code behind is calling container.GetInstance(typeof(DataContext))
var db = ResolvingActivator.CreateInstance<DataContext>();
return db.Table.Any();
}
}
Any ideas where I'm going wrong?
Edit: here is the stack trace from the ActivationException:
at SimpleInjector.Scope.GetScopelessInstance[TImplementation](ScopedRegistration`1 registration)
at SimpleInjector.Scope.GetInstance[TImplementation](ScopedRegistration`1 registration, Scope scope)
at SimpleInjector.Advanced.Internal.LazyScopedRegistration`1.GetInstance(Scope scope)
at lambda_method(Closure )
at SimpleInjector.InstanceProducer.GetInstance()
at SimpleInjector.Container.GetInstance(Type serviceType)
at Service.Core.ResolvingActivator.CreateInstance(Type type) in Service.Core\ResolvingActivator.cs:line 43
at Service.Core.ResolvingActivator.CreateInstance(String typeName) in Service.Core\ResolvingActivator.cs:line 35
at Service.Core.ResolvingActivator.CreateInstance[TService](String typeName) in Service.Core\ResolvingActivator.cs:line 69
With a full stack trace here: https://pastebin.com/0WkyHGKv
After close inspection of the stack trace, I can conclude what's going on: async.
The WcfOperationLifestyle under the covers depends on WCF's OperationContext.Current property, but this property has a thread-affinity and doesn't flow with async operations. This is something that has to be fixed in the integration library for Simple Injector; it simply doesn't support async at the moment.
Instead, wrap a decorator around your handlers that start and end a new async scope. This prevents you from having to use the WcfOperationLifestyle all together. Take a look at the ThreadScopedCommandHandlerProxy<T> implementation here to get an idea how to do this (but use AsyncScopedLifestyle instead).

sharp architecture contrib transaction attribute in windows service

For some reason this:
[Transaction]
public void DoSomething()
{
...
}
does not work I still have to explicitly use the transaction like this:
public void DoSomething()
{
using (var tx = NHibernateSession.Current.BeginTransaction())
{
....
tx.Commit();
}
}
Any ideas why?
I am using something like this to bootstrap stuff:
_container = new WindsorContainer();
ComponentRegistrar.AddComponentsTo(_container);
...
ServiceLocator.SetLocatorProvider(() => new WindsorServiceLocator(_container));
ComponentRegistrar.AddComponentsTo(_container, typeof(NHibernateTransactionManager));
NHibernateSession.Init(new ThreadSessionStorage(),
new[] { "Bla.Domain.dll" },
new AutoPersistenceModelGenerator().Generate(),
"NHibernate.config");
As Doan said the component that had the method is not proxied.
Since the method is not virtual, I am assuming that your class is implementing an interface. make sure that you have the dependency in the class calling DoSomething defined as the interface and not the implementing class.
if you debug the code, and check the run time type of the object, it should be a castle proxy
for more details check the trouble shooting section on Sharp Architecture contrib wiki
https://github.com/sharparchitecture/Sharp-Architecture-Contrib/wiki/Troubleshooting
Normally, this kind of problem is caused by the failure of invoking the dynamic proxy that provides the transaction management service. Two of the most common errors are:
The method cannot be proxied: most likely not implement any interface method, or the object was not proxied.
The method was called from the same class, which bypassed all proxies.
Edit:
I guess you use Castle Windsor as IoC container. The [Transaction] decoration requires the Automatic Transaction Management Facility in order to work. If you successfully configured the facility, i.e. you made [Transaction] work in one method, but not other, then the answer above applies. If all Transaction decoration failed to work, then you have to review the configuration of the facility first.

How to decorate interfaces bound to more than one concrete type with Ninject

So, I have a message bus that instantiates message handlers through Ninject. I'd like to decorate my handlers with cross cutting concerns such as logging, transaction management, etc.
I setup my bindings like so:
kernel.Bind<IMessageHandler<int>>().To<IntHandlerOne>()
.WhenInjectedInto(typeof(HandlerDecorator<>));
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>));
Which works fantastically whenever I have a single handler of a specific message type. However, when I have more than one handler defined:
kernel.Bind<IMessageHandler<int>>().To<IntHandlerOne>()
.WhenInjectedInto(typeof(HandlerDecorator<>));
kernel.Bind<IMessageHandler<int>>().To<IntHandlerTwo>()
.WhenInjectedInto(typeof(HandlerDecorator<>));
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>));
Ninject will find and inject the decorator to the message bus, and then attempt unsuccessfully to inject both handlers into the decorator constructor.
public HandlerDecorator(IMessageHandler<T> handler)
You may be thinking, why don't I just modify my decorator to accept the list of handlers? I thought about this, but that defeats the purpose of the handler. I want to be able to easily chain multiple decorators together transparently. Each instance of IMessageHandler<T> should get an entirely new chain of handlers.
I've published an example test library on GitHub that should illustrate what I'm talking about here.
Is there any way to do this in Ninject?
Use
kernel.Bind<IMessageHandler<int>>().To<IntHandlerOne>().WhenParentNamed("One");
kernel.Bind<IMessageHandler<int>>().To<IntHandlerTwo>().WhenParentNamed("Two");
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>)).Named("One");
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>)).Named("Two");
Also be aware that most of the Bus Frameworks have some way to do decorations for message handlers. May have a look there first.
You should wrap those handlers in a composite:
public class CompositeMessageHandler<T> : IMessageHandler<T>
{
private readonly IEnumerable<IMessageHandler<T>> handlers;
CompositeMessageHandler(IEnumerable<IMessageHandler<T>> handlers)
{
this.handlers = handlers;
}
public void Handle(T message)
{
foreach (var handler in this.handlers)
{
handler.Handle(message);
}
}
}
This composite can again be injected into your decorator. Or perhaps you should do it the other way around: Wrap each handler with a decorator and wrap those into the composite.
I'm not sure how to register this with Ninject though.

Late binding with Ninject

I'm working on a framework extension which handles dynamic injection using Ninject as the IoC container, but I'm having some trouble trying to work out how to achieve this.
The expectation of my framework is that you'll pass in the IModule(s) so it can easily be used in MVC, WebForms, etc. So I have the class structured like this:
public class NinjectFactory : IFactory, IDisposable {
readonly IKernel kernel;
public NinjectFactory(IModule[] modules) {
kernel = new StandardKernel(modules);
}
}
This is fine, I can create an instance in a Unit Test and pass in a basic implementation of IModule (using the build in InlineModule which seems to be recommended for testing).
The problem is that it's not until runtime that I know the type(s) I need to inject, and they are requested through the framework I'm extending, in a method like this:
public IInterface Create(Type neededType) {
}
And here's where I'm stumped, I'm not sure the best way to check->create (if required)->return, I have this so far:
public IInterface Create(Type neededType) {
if(!kernel.Components.Has(neededType)) {
kernel.Components.Connect(neededType, new StandardBindingFactory());
}
}
This adds it to the components collection, but I can't work out if it's created an instance or how I create an instance and pass in arguments for the .ctor.
Am I going about this the right way, or is Ninject not even meant to be be used that way?
Unless you want to alter or extend the internals of Ninject, you don't need to add anything to the Components collection on the kernel. To determine if a binding is available for a type, you can do something like this:
Type neededType = ...;
IKernel kernel = ...;
var registry = kernel.Components.Get<IBindingRegistry>();
if (registry.Has(neededType)) {
// Ninject can activate the type
}
Very very late answer but Microsoft.Practices.Unity allows Late Binding via App.Config
Just in case someone comes across this question