What I am trying to do is wrap a decorator around a command using the following code.
public interface ICommand
{
}
public interface ICommand<T> : ICommand where T : class
{
void Execute(T args);
}
public class TransactionalCommand<T> : ICommand<T>
where T : class
{
private readonly ICommand<T> command;
public TransactionalCommand(ICommand<T> command)
{
this.command = command;
}
public void Execute(T args)
{
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
this.command.Execute(args);
scope.Complete();
}
}
}
Here is how I am invoking the resolve but i only get back my ChangePasswordCommand without the decoratoration. (Actually it wont event compile on the second Bind)
The ultimate goal is to have this auto-register all my types using this decorator. Any help would be great!
Bind<ChangePasswordCommand>().To<ChangePasswordCommand>()
.WhenInjectedInto<TransactionalCommand<ChangePasswordArgs>>();
Bind<ChangePasswordCommand>().To<TransactionalCommand<ChangePasswordArgs>>()
.InTransientScope();
var command = kernel.Get<ChangePasswordCommand>();
You were pretty close. However: when you want to use a decorator you need the decorator to implement the same interface as the command. That's the case here, but you'll also need to resolve that interface (and bind it, too). So here's how it works:
kernel.Bind<ICommand<ChangePasswordArgs>>().To<ChangePasswordCommand>()
.WhenInjectedInto<TransactionalCommand<ChangePasswordArgs>>();
kernel.Bind<ICommand<ChangePasswordArgs>>().To<TransactionalCommand<ChangePasswordArgs>>()
.InTransientScope();
var command = kernel.Get<ICommand<ChangePasswordArgs>>();
Related
I've created this code:
public class AddonsModule : Ninject.Modules.NinjectModule
{
public override void Load()
{
this.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom(typeof(UIExtensibility.AbstractAddon))
.BindWith(new AddonBindingGenerator())
);
}
private class AddonBindingGenerator : IBindingGenerator
{
public System.Collections.Generic.IEnumerable<Ninject.Syntax.IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(System.Type type, Ninject.Syntax.IBindingRoot bindingRoot)
{
if (type.IsInterface || type.IsAbstract)
yield break;
yield return bindingRoot.Bind(type).ToProvider(typeof(UIExtensibility.AbstractAddon));
}
}
private class AddonProvider : IProvider<UIExtensibility.AbstractAddon>
{
public object Create(IContext context)
{
return null;
}
public Type Type
{
get { throw new NotImplementedException(); }
}
}
}
AddonProvider seems be avoided. This is never performed.
When I perform:
kernel.GetAll<UIExtensibility.AbstractAddon>(), AddonProvider.Create method is never performed.
Could you tell me what's wrong?
I'll appreciate a lot your help.
Thanks for all.
AddOnProvider is inheriting from IProvider<T> instead of UIExtensibility.AbstractAddon.
also, you may have issues binding to private inner classes. make AddOnProvider a public top level class.
You're binding a specific type which inherits from typeof(UIExtensibility.AbstractAddon) to a provider. For example, there could be a class Foo : UIExtensibility.AbstractAddon.
Now your convention binding translates to this:
Bind<Foo>().ToProvider<AddonProvider>();
Now, kernel.GetAll<UIExtensibility.AbstractAddon>() however is looking for bindings made like:
Bind<UIExtensibility.AbstractAddon>().To...
Fix It
So what you need to do is change the line
bindingRoot.Bind(type).ToProvider(new AddonProvider());
to:
bindingRoot.Bind(typeof(UIExtensibility.AbstractAddon)).ToProvider<AddonProvider>();
Furthermore
you're line object f = bindingRoot.Bind(type).ToProvider(new AddonProvider()); is never returning the binding (object f).
does UIExtensibility.AbstractAddon implement IProvider?
Thanks for your answer and comments.
I believe the trouble is on I'm not quite figuring out how this "generic" binding process works.
I'm going to try writing my brain steps process out:
I need to bind every AbstractAddon implementation inside addons assemblies folder. So, I think this code is right, but I'm not sure at all.
this.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom(typeof(UIExtensibility.AbstractAddon))
.BindWith(new AddonBindingGenerator())
);
My AbstractAddon is like:
public abstract class AbstractAddon : IAddon
{
private object configuration;
public AbstractAddon(object configuration)
{
this.configuration = configuration;
}
// IAddon interface
public abstract string PluginId { get; }
public abstract string PluginVersion { get; }
public abstract string getCaption(string key);
public abstract Type getConfigurationPanelType();
public abstract System.Windows.Forms.UserControl createConfigurationPanel();
}
I guess I need to:
foreach implementation of `AbstractAddon` found out,
I need to "inject" a configuration object ->
So, I guess I need to set a provider and provide this configuration object.
This would be my main way of thinking in order to solve this problem.
I've changed a bit my first approach. Instead of using a IBindingGenerator class, I've used the next:
public class AddonsModule : Ninject.Modules.NinjectModule
{
public override void Load()
{
this.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom(typeof(UIExtensibility.AbstractAddon))
.BindAllBaseClasses()
.Configure(c => c.InSingletonScope())
);
this.Bind<object>().ToProvider<ConfigurationProvider>()
.WhenTargetHas<UIExtensibility.ConfigurationAttribute>();
}
So, My ConfigurationProvider is:
private class ConfigurationProvider : IProvider<object>
{
public object Create(IContext context)
{
return "configuration settings";
}
}
And now, my AbstractAddon constructor contains the parameter annotated with ConfigurationAttribute as:
public AbstractAddon([Configuration]object configuration)
{
this.configuration = configuration;
}
The problem now, NInject seems to ignore the configuration object provider. NInject generates a dump object, however, not perform ConfigurationProvider.Create method...
What I'm doing wrong, now?
Is this approach really better than the last one?
Thanks for all.
Just wanted to know if there is a way bind a type and resolve a collection. I dont know if Ninject can do this out of the box. I'm using MVC4 with Ninject3 so I have the NinjectWebCommon.cs where I register the services. There is nowhere I can get the kernel (I read that it was bad practice to access the kernel from elsewhere, but that can certainly be the solution to this).
For example, I'm having this class:
public class CacheManager
{
public IEnumerable<SelectListItem> Get<T>() where T : INameValue
I want to be able to send
CacheManager.Get<City>
and obtain the CityRepository class.
Is it this you want to do? :
using System.Collections.Generic;
using System.Linq;
using Ninject;
using Ninject.Modules;
using Ninject.Syntax;
public class Temp
{
public interface ICity { }
public class SelectListItem
{
}
public class FooCity : SelectListItem, ICity { }
public class BarCity : SelectListItem, ICity {}
public class CityModule : NinjectModule
{
public override void Load()
{
this.Bind<ICity>().To<FooCity>();
this.Bind<ICity>().To<BarCity>();
}
}
public class CacheManager
{
private readonly IResolutionRoot resolutionRoot;
public CacheManager(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public IEnumerable<SelectListItem> Get<T>()
{
return this.resolutionRoot.GetAll<T>().OfType<SelectListItem>();
}
}
}
I'm unclear as to whether you have multiple implementations of T (ICity) or one implementation but several instances (like retrieving a list of city names from the database and creating one instance per name). The later you could solve by a this.Bind>().ToProvider(...) binding.
I ended up doing:
In NinjectWebCommon.cs:
kernel.Bind(typeof(CacheManager))
.ToSelf()
.InSingletonScope();
kernel.Bind<IDataListRepository<Locale>>()
.To<LocaleRepository>();
In CacheManager.cs:
public class CacheManager: IDisposable
{
private IKernel kernel;
public CacheManager(IKernel kernel)
{
this.kernel = kernel;
}
public IEnumerable<T> GetAsEnumerable<T>()
{
var rep = kernel.Get<IDataListRepository<T>>();
return rep.GetAll();
}
I don't know if this is bad-practice (since kernel in theory should only be used in the initialization phase), but I didn't find any other way to do it.
If better options exist, please let me know.
I am trying to use ServiceStack with Ninject rather than Funq. I have the following:
public interface IContainerAdapter
{
T Resolve<T>();
T TryResolve<T>();
}
public class NinjectIocAdapter : IContainerAdapter
{
private readonly IKernel kernel;
public NinjectIocAdapter(IKernel kernel)
{
this.kernel = kernel;
}
public T Resolve<T>()
{
return this.kernel.Get<T>();
}
public T TryResolve<T>()
{
return this.kernel.TryGet<T>();
}
}
Then inside my Configure method:
public override void Configure(Funq.Container container)
{
//Set JSON web services to return idiomatic JSON camelCase properties
ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;
IKernel kernel = new StandardKernel();
container.Adapter = new NinjectIocAdapter(kernel);
//Set MVC to use the same Funq IOC as ServiceStack
//ControllerBuilder.Current.SetControllerFactory(new FunqControllerFactory(container));
}
But I get the following error:
Cannot implicitly convert type 'NinjectIocAdapter' to 'ServiceStack.Configuration.IContainerAdapter'.
I'm also unsure whether I have to uncomment the line to set MVC to use Funq IoC? I have commented it out as I will be using Ninject. Is that correct?
I assume once this is all working. I can simply register any dependencies inside:
private static void RegisterServices(IKernel kernel)
{
}
The code exactly matches the documentation with one subtle difference.
You have to use ServiceStack.Configuration.IContainerAdapter instead of your own IContainerAdapter
.
Delete your implementation, add a reference to ServiceStack.Configuration and you should be fine.
Below's code is working fine, and successfully create an instance for class DummyComponnent.
But the problem arises when i had changed the factory method name CreatDummyComponnent()
to GetDummyComponnent() or anything else except Creat as the beginning of method name, say AnyThingComponent throws an exception. is there any specify naming rule for factory methods ?
using System;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
namespace AsFactoryImplementation
{
public interface IDummyComponnentFactory
{
IDummyComponnent CreatDummyComponnent();
// void Relese(IDummyComponnent factory);
}
public interface IDummyComponnent
{
void Show();
}
public class DummyComponnent:IDummyComponnent
{
public DummyComponnent()
{
Console.WriteLine("we are working here");
}
public void Show()
{
Console.WriteLine("just testing this for better performance");
}
}
class Program
{
static void Main(string[] args)
{
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IDummyComponnent>().ImplementedBy<DummyComponnent>().Named("FirstConnection"),
Component.For<IDummyComponnentFactory>().AsFactory());
var val = container.Resolve<IDummyComponnentFactory>();
var iDummy = val.CreatDummyComponnent();
iDummy.Show();
Console.WriteLine("OK its done ");
Console.ReadLine();
}
}
}
You should be able to use anything for starting the method names on the Factory, except for starting with Get.
If you start with Get it will try to resolve the component by name instead of by interface.
So what would work in your example is:
var iDummy = val.GetFirstConnection();
Good luck,
Marwijn.
Here is the set up that is not working
Using Ninject V3.0
public class LoggerModule : NinjectModule{
public override void Load()
{
Bind<ILogger>.ToProvider(MyLoggerProvider);
}
}
public class MyLoggerProvider: IProvider<ILogger>
{
public object Create(IContext context){
return new OneOfMyLoggers();
}
}
In my application wherever I inject instance of ILogger (using constructor or property injection, just does matter) I never get instance of ILogger resolved.
But If do not use module and/or povider, and bind when kernel is created, everything works like a charm. The following works
public class MyDiResolver()
{
public MyDiResolver()
{
MyKernel = new StandardKernel();
MyKernel.Bind<ILogger>().To<OneOfMyLoggers>();
}
}
The same arrangement of modules and providers works fine in Ninject2.x version. Is there something different about Ninject V3.0 that I am missing?
Thanks
Try passing the module into the StandardKernel so it knows to use it:
using (IKernel kernel = new StandardKernel(new LoggerModule()))
{
ILogger logger = kernel.Get<OneOfMyLoggers>();
}