c# - Ninject equivalent to Autofac IIndex -
is there ninject equivalent autofac iindex. in other words need collections of registered items have name of registration. in autofac edit: made change make things more clear.
static void main(string[] args) { var builder = new containerbuilder(); builder.registertype<add>().keyed<icommand>("add"); builder.registertype<add>().keyed<icommand>("sub"); builder.registertype<calculator>().as<calculator>(); var container = builder.build(); var calc = container.resolve<calculator>(); calc.run(); } public class calculator { iindex<string, icommand> commands; public calculator(iindex<string, icommand> commands) { this.commands = commands; } public void run() { var result = true; { var cmd = console.readline().split(' '); icommand command; if (commands.trygetvalue(cmd[0], out command)) { result = command.do(cmd.skip(1).toarray()); } else { console.writeline("command not found"); } } while (!result); } } public interface icommand { bool do(string[] data); } public class add : icommand { public bool do(string[] data) { console.writeline(double.parse(data[0]) + double.parse(data[1])); return false; } } public class substract : icommand { public bool do(string[] data) { console.writeline(double.parse(data[0]) - double.parse(data[1])); return false; } }
but unable find how in ninject.
as in link provided, intending value key
.
what searching called named binding. bindings identified name. how ever problem here is, need use common injection strategies of ninject.
bind<idevicestate>().to<onlinestate>().named("online"); bind<idevicestate>().to<offlinestate>().named("offline"); public modem([named("online")] idevicestate state){ _state = state; }
this way, can choose implementation of idevicestate
injected namedattribute
, added right before injection parameter. doesn't work out you, because want create idevicestate
s on fly. thats why need use ninject.extensions.factory.
this allow inject idevicestatefactory
.
public interface idevicestatefactory { idevicestate getonline(); idevicestate getoffline(); }
those factorys underlie specific syntax, get
-methods resolve named binding described above. getonline()
match bind<idevicestate>().to<onlinestate>().named("online")
binding , return instance of onlinestate
.
just tell ioccontainer
idevicestatefactory
factory. implementation of interface automatically provided ninject's proxy system.
bind<idevicestatefactory>().tofactory();
so how imlpement class modem
using technique
public class modem : ihardwaredevice { idevicestatefactory _statefactory; idevicestate _currentstate; public modem(idevicestatefactory statefactory) { _statefactory = statefactory; switchon(); } void switchon() { _currentstate = _statefactory.getonline(); } }
using real key
however if want use devicestate
-enumeration before, use approach described here.
the binding pretty this:
const string enumkey = "enumkey"; bind<idevicestate>().to<onlinestate>() .withmetadata(enumkey, devicestate.online);
use method resolve using devicestate.online
key
iresolutionroot.get<idevicestate>(x => x.get<devicestate>(enumkey) == devicestate.online);
but in opinion, there no reason such complicated thing. recommend forget whole iindex<tkey, tsource>
mechanics autofac , ninject way.
your edit: preserving iindex (solution involving factory extension)
well, iindex
, no such thing exist in ninject, create own implementation of it, inheriting idictionary
, or define alike , defining follows:
public interface iindex<tkey, tvalue> { bool trygetvalue(tkey key, out tvalue value); tvalue this[tkey key] { get; set; } }
the factory above gets icommandfactory
public interface icommandfactory { icommand getadd(); icommand getsubtract(); }
then need create implementation of iindex
using icommandfactory
resolve actual command instances.
public class commandindex : iindex<string, icommand> { private readonly icommandfactory _factory; public commandindex(icommandfactory factory) { _factory = factory; } public bool trygetvalue(string key, out icommand value) { switch (key) { case "add": value = _factory.getadd(); break; case "subtract": value = _factory.getsubtract(); break; default: value = null; break; } return value != null; } public icommand this[string key] { { icommand value; trygetvalue(key, out value); return value; } set { throw new notsupportedexception();} } }
but need ask you: whole thing necessary? man use factory. gets less complicated.
another attempt of preserving iindex without factory extension
another attempt propably less coding directly using ikernel
propably bad practice. can resolve named bindings this:
public class namedbindingindex<tvalue> : iindex<string, tvalue> { private readonly ikernel _kernel; public namedbindingindex(ikernel kernel) { _kernel = kernel; } public bool trygetvalue(string key, out tvalue value) { value = _kernel.get<tvalue>(key); // catch exception here return value != null; } public tvalue this[string key] { { tvalue value; trygetvalue(key, out value); return value; } set { throw new notsupportedexception(); } } }
just bind this
bind<iindex<string, icommand>>().to<namedbindingindex<icommand>>();
and solution should working pretty same. plus is, last attempt doesn't need no ninject.extensions.factory.
Comments
Post a Comment