.net - How to pass parameters into constructors when using IoC containers? -


arrrgh! pulling hair on here. have been trying use ioc containers little bit, , seems fine , dandy until hit issue think basic, passing parameters constructors.

say have class somewhere mix of reference classes can resolved ioc , value types (or other types) can resolved @ runtime:

public nflfeedunitofwork(nflfiletype filetype, object feed, iconvertermappings<nflfiletype> nflconvertermappings, idbcontext context)     : base(filetype, feed, nflconvertermappings, context, contexttype.nfl) {     //new nflcontext(connstringname, setautodetectchanges) } 

in particular example pass in enum (nflfiletype), object instance, 2 interface parameters , pass in 1 hardcoded property base constructor (contexttype.nfl)

how in name of gods can in ioc container?

the problem 2-fold:

1.) how pass in object known @ runtime? example calling code looks @ moment:

protected override ifeedunitofwork getunitofwork(nflfiletype filetype, object feed, string connectionstring) {     return new nflfeedunitofwork(filetype, feed, new nflconvertermappings(), new nflcontext(connectionstring)); } 

how can convert code using ioc? perhaps this?

protected override ifeedunitofwork getunitofwork(nflfiletype filetype, object feed, string connectionstring) {     return iflfeedunitofwork(filetype, feed); } 

where last 2 parameters automatically resolved, , 1st 2 supply myself?

2.) how can pass in enum, object, value types constructor using ioc? (or maybe refrain using in particular instance?)

anyway, appreciated, on 1st point. using unity @ moment, other ioc container fine well.

i don't want pass in ioc container code either, want specify in 1 place @ top level.

i have class somewhere mix of reference classes can resolved ioc , value types (or other types) can resolved @ runtime

this go wrong. should not mix compile time dependencies runtime data when compose components. object graphs should static (and preferably stateless) , runtime data should passed through object graph using method calls after complete object graph constructed. can cause tremendous simplification in development of application, because allows object graphs statically verified (using tool, unit tests or using pure di) , prevents having trouble having today.

in general, have 2 options solve this:

  1. you pass data on lower level components through method calls.
  2. you retrieve data calling method on injected component.

which solution take depends on context.

you typically go option 1 in case data specific handled request , part of use case you're handling. instance:

public interface ifeedunitofworkprovider {     ifeedunitofwork getunitofwork(nflfiletype filetype, object feed); } 

here ifeedunitofworkprovider contains getunitofwork method requires runtime parameters input. implementation might this:

public class feedunitofworkprovider : ifeedunitofworkprovider {     private readonly iconvertermappings convertermappings;     private readonly icontext context;      public feedunitofworkprovider(iconvertermappings convertermappings,         icontext context) {         this.convertermappings = convertermappings;         this.context = context;     }      public ifeedunitofwork getunitofwork(nflfiletype filetype, object feed) {         return new nflfeedunitofwork(filetype, feed, this.convertermappings,             this.context);     }        } 

a few things note here:

  • all statically known dependencies injected through constructor, while runtime values injected through method calls.
  • the connectionstring value unknown feedunitofworkprovider. it's not direct dependency , provider doesn't have know existence.
  • assuming connectionstring configuration value not change @ runtime (and typically stored in application's configuration file), can injected nflcontext same way other dependencies injected. note configuration value different runtime value, because won't change during lifetime of application.

the second option useful when you're dealing contextual information. information important implementation, should not passed in previous example. example of information user on whos behalf request running. typical abstraction this:

public interface iusercontext {     string currentusername { get; } } 

this interface can injected consumer. using abstraction, consumer can query user name @ runtime. passing through user name rest of request data typically awkward, because allow caller change (or forget) user name, making code harder work with, harder test, more error prone. instead can use iusercontext:

public ifeedunitofwork getunitofwork(nflfiletype filetype, object feed) {     if (this.usercontext.currentusername == "steven") {         return new adminunitofwork(this.context);     }     return new nflfeedunitofwork(filetype, feed, this.convertermappings,         this.context); } 

how iusercontext implementation should highly depend on type of application you're building. asp.net imagine this:

public class aspnetusercontext : iusercontext {     string currentusername {         { return httpcontext.current.user.name; }     } } 

Comments