ioc container - Is it possible to use Ninject Factory Extensions' ToFactory method with open generics? -
i'm building on answered question in icar
implementations bound using ninject conventions extensions , custom ibindinggenerator, , icarfactory
interface bound using ninject factory extensions' tofactory()
method , custom instance provider.
i'm trying refactor can bind , make use of ivehiclefactory<t>
, t
constrained icar
, rather previous icarfactory
. way, can specify vehicle want in generic type parameter, instead of passing in name of vehicle type in factory's createcar()
method.
is possible bind open generic interfaces using tofactory()
technique?
i have feeling i'm barking wrong tree, when specifying icar
type name, seemed natural evolution specify icar
type generic type parameter...
here's test fails:
[fact] public void a_generic_vehicle_factory_creates_a_car_whose_type_equals_factory_method_generic_type_argument() { using (standardkernel kernel = new standardkernel()) { // arrange kernel.bind(typeof(ivehiclefactory<>)) .tofactory(() => new usefirstgenerictypeargumentinstanceprovider()); kernel.bind( scanner => scanner .fromthisassembly() .selectallclasses() .inheritedfrom<icar>() .bindwith(new basetypebindinggenerator<icar>())); ivehiclefactory<mercedes> factory = kernel.get<ivehiclefactory<mercedes>>(); // act var car = factory.createvehicle(); // assert assert.istype<mercedes>(car); } }
and invalidcastexception
thrown:
system.invalidcastexception unhandled user code message=unable cast object of type 'castle.proxies.objectproxy' type 'ivehiclefactory`1[mercedes]'. source=system.core stacktrace: @ system.linq.enumerable.<castiterator>d__b1`1.movenext() @ system.linq.enumerable.single[tsource](ienumerable`1 source) @ ninject.resolutionextensions.get[t](iresolutionroot root, iparameter[] parameters) in c:\projects\ninject\ninject\src\ninject\syntax\resolutionextensions.cs:line 37 @ ninjectfactorytests.a_generic_vehicle_factory_creates_a_car_whose_type_name_equals_factory_method_string_argument() in c:\programming\ninject.extensions.conventions.tests\ninjectfactorytests.cs:line 37 innerexception:
and factory interface:
public interface ivehiclefactory<t> t : icar { t createvehicle(); }
and custom instance provider, breakpoints can't debugger stop on, don't know what's going on in there:
public class usefirstgenerictypeargumentinstanceprovider : standardinstanceprovider { protected override string getname(methodinfo methodinfo, object[] arguments) { var generictypearguments = methodinfo.getgenericarguments(); var genericmethoddefinition = methodinfo.getgenericmethoddefinition(); var g = genericmethoddefinition.makegenericmethod(generictypearguments.first()); return g.membertype.gettype().name; } protected override constructorargument[] getconstructorarguments(methodinfo methodinfo, object[] arguments) { return base.getconstructorarguments(methodinfo, arguments).skip(1).toarray(); } }
edit 1 - change ivehiclefactory
signature , custom instance provider
here's i've changed ivehiclefactory
signature use generic create<t>()
method, , explicitly bound mercedes
itself.
public interface ivehiclefactory { t createvehicle<t>() t : icar; }
and new custom instance provider returns name of first generic type parameter:
public class usefirstgenerictypeargumentinstanceprovider : standardinstanceprovider { protected override string getname(methodinfo methodinfo, object[] arguments) { var generictypearguments = methodinfo.getgenericarguments(); return generictypearguments[0].name; } }
here's new test, still not passing:
[fact] public void a_generic_vehicle_factory_creates_a_car_whose_type_name_equals_factory_method_string_argument() { using (standardkernel kernel = new standardkernel()) { // arrange kernel.bind<ivehiclefactory>() .tofactory(() => new usefirstgenerictypeargumentinstanceprovider()) .insingletonscope(); kernel.bind<mercedes>().toself(); ivehiclefactory factory = kernel.get<ivehiclefactory>(); // act var car = factory.createvehicle<mercedes>(); // assert assert.istype<mercedes>(car); } }
}
a ninject.activationexception
thrown:
ninject.activationexception: error activating mercedes no matching bindings available, , type not self-bindable. activation path: 1) request mercedes
i don't know why can't find mercedes
class, since explicitly self-bound it. can spot i'm doing wrong?
use generic methods:
public interface ivehiclefactory { createvehicle<t>(); }
Comments
Post a Comment