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

Popular posts from this blog

android - getbluetoothservice() called with no bluetoothmanagercallback -

sql - ASP.NET SqlDataSource, like on SelectCommand -

ios - Undefined symbols for architecture armv7: "_OBJC_CLASS_$_SSZipArchive" -