Constructing with a given dependency

8 views
Skip to first unread message

Jimmy Bogard

unread,
Jul 16, 2008, 11:33:32 AM7/16/08
to structuremap-users
I'm trying to create an instance of a service, with the caveat that
during instantiation, I want to use a specific instance for a
dependency. But only for that single call:

IFoo foo = new Foo();

Type type = someRequestedType;

ObjectFactory.UsingDependency(foo).GetInstance(type);

I know some dependency inside the "someRequestedType" needs IFoo.
GetInstance would use inject the foo instance wherever something
depended on IFoo, but only for this single GetInstance call. All
other times it would use the regular configuration rules.

Is this possible in 2.4.9?

Thanks

Jeremy Miller

unread,
Jul 16, 2008, 11:56:17 AM7/16/08
to structuremap-users
Jimmy,

Try:

ObjectFactory.With<IFoo>(foo).GetInstance<RequestedType>();




Jimmy Bogard

unread,
Jul 24, 2008, 12:00:12 PM7/24/08
to structuremap-users
I tried to make this test pass (it fails right now):

[Test]
public void ObjectFactory_with_works_correctly()
{

StructureMapConfiguration.ForRequestedType<IBar>().TheDefaultIsConcreteType<Bar>();

StructureMapConfiguration.ForRequestedType<IFoo>().TheDefaultIsConcreteType<Foo>();

IBar first = ObjectFactory.GetInstance<IBar>();
first.GetValue().ShouldEqual(50);

Foo other = new Foo(100);
IBar second = ObjectFactory.With(other).GetInstance<IBar>();

second.GetValue().ShouldEqual(100);
}

public interface IFoo
{
int GetValue();
}

public interface IBar
{
int GetValue();
}

public class Foo : IFoo
{
public int Value = 50;

[DefaultConstructor]
public Foo() { }

public Foo(int value)
{
Value = value;
}

public int GetValue()
{
return Value;
}
}

public class Bar : IBar
{
private readonly IFoo _foo;

public Bar(IFoo foo)
{
_foo = foo;
}

public int GetValue()
{
return _foo.GetValue();
}
}

Do I have the usage of ObjectFactory.With wrong here?

paul

unread,
Jul 25, 2008, 4:20:06 AM7/25/08
to structuremap-users
Try

Foo other = new Foo(100);
IBar second = ObjectFactory.With<IFoo>(other).GetInstance<IBar>();

-p

Jimmy Bogard

unread,
Jul 28, 2008, 8:44:45 AM7/28/08
to structure...@googlegroups.com
Yep, that worked!

Jimmy Bogard

unread,
Jul 28, 2008, 11:59:28 AM7/28/08
to structuremap-users
Now that seems to work only when the specified instance is a
dependency of the type being requested, not on any child types. For
instance, if you introduced an IBuzz into the mix, that depends on
IBar, it won't wire up your custom Foo implementation.

On Jul 28, 7:44 am, "Jimmy Bogard" <jimmy.bog...@gmail.com> wrote:
> Yep, that worked!
>

Jeremy Miller

unread,
Jul 28, 2008, 1:06:01 PM7/28/08
to structuremap-users
Ok, so basically you need the "I say that the IBuzz is this, so
anybody, anywhere who needs an IBuzz gets the one I say"

Is that about right? Right now the way the functionality is built,
this does not work except for the top level guy being requested. I
can think of an easy way to fix this issue. I'll get back to you.

Josh Flanagan

unread,
Jul 28, 2008, 1:40:45 PM7/28/08
to structure...@googlegroups.com
I *think* he means:
"I say that the IBuzz is this, so anybody, anywhere WITHIN THE
DEPENDENCY GRAPH FOR THIS CALL TO GETINSTANCE who needs an IBuzz gets
the one I say"

If you just want to say, anybody anywhere, any TIME going forward
should get this, you can do:
(Assume default IBuzz has a dependency on IBar, default IBar has a
dependency on IFoo)

Foo other = new Foo(100);

ObjectFactory.Inject<IFoo>(other);
var buzz = ObjectFactory.GetInstance<IBuzz>();

The problem with this solution is that now the "other" instance of
IFoo will always be used, for anything that asks for it in the future.


I wonder if you could do something like:

IFoo defaultConfiguredIFoo = ObjectFactory.GetInstance<IFoo>();


Foo other = new Foo(100);

ObjectFactory.Inject<IFoo>(other);

// make the call to use the special IFoo
var buzz = ObjectFactory.GetInstance<IBuzz>();

// revert things so that other calls do NOT get the special IFoo
ObjectFactory.Inject<IFoo>(defaultConfiguredIFoo);


Now, assuming that works (and I'm not misunderstanding the behavior of
the Inject method), StructureMap could add some sugar to allow
something like:

using (ObjectFactory.CreateScope().For<IFoo>(other)){
var buzz = ObjectFactory.GetInstance<IBuzz>();
}
var buzz2 = ObjectFactory.GetInstance<IBuzz>();

In this case, buzz gets my specific IFoo, and buzz2 gets the default IFoo.

Jimmy Bogard

unread,
Jul 28, 2008, 2:19:55 PM7/28/08
to structuremap-users
Right. "Anybody, anywhere", but for this _one_ call to GetInstance.
For the scope of this one resolution, use this one instance.

This all came about from trying to do Session per Conversation w/ SM,
WCF and NHibernate, opening a session at the start of a request and
closing it at the end.

To answer Josh's reply, I can't use Inject, mostly because WCF's
threading model is controlled via configuration and I can't assume
anything there. This was a lot easier with ASMX.

Jeremy Miller

unread,
Jul 28, 2008, 2:22:18 PM7/28/08
to structuremap-users
I can make a small change to make With<T>() act as "use this anywhere
in the entire object graph for only this 'BuildSession'"

It's not actually that big of a change, and if you're hitting this
with WCF, someone else will too.

You know what would be really, really awesome Jimmy? A blog post on
using WCF with IoC.

Jimmy Bogard

unread,
Jul 29, 2008, 11:49:26 PM7/29/08
to structuremap-users
Yeah, yeah

http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/07/29/integrating-structuremap-with-wcf.aspx

Maybe further down the line, but I definitely ran into some pain where
I couldn't use the generic goodness, and there weren't System.Type
equivalents, mostly around the StructureMapConfiguration stuff. It
was fun creating the
IServiceHostFactoryBehaviorInstanceProviderPluginProviderProvider
implementations, let me tell you...

walkf...@gmail.com

unread,
Aug 22, 2008, 5:55:46 AM8/22/08
to structuremap-users
@Jims suggestion I am posting a question I had from his blog.

'I have implemented all of the changes to my app but I am having an
issue setting up the default instance in WCF. I have seen posts that
setup the interface to a concrete class in code(e.g. a Registry), but
I must be missing something when implementing this in WCF, how do you
do this in a WCF app?'


On Jul 29, 10:49 pm, Jimmy Bogard <jimmy.bog...@gmail.com> wrote:
> Yeah, yeah
>
> http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/07/29/integ...
>
> Maybe further down the line, but I definitely ran into some pain where
> I couldn't use the generic goodness, and there weren't System.Type
> equivalents, mostly around the StructureMapConfiguration stuff.  It
> was fun creating the
> IServiceHostFactoryBehaviorInstanceProviderPluginProviderProvider
> implementations, let me tell you...
>
> On Jul 28, 1:22 pm, Jeremy Miller <jeremydmil...@yahoo.com> wrote:
>
>
>
> > I can make a small change to make With<T>() act as "use this anywhere
> > in the entire object graph for only this 'BuildSession'"
>
> > It's not actually that big of a change, and if you're hitting this
> > withWCF, someone else will too.
>
> > You know what would be really, really awesome Jimmy?  A blog post on
> > usingWCFwith IoC.- Hide quoted text -
>
> - Show quoted text -

Jimmy Bogard

unread,
Aug 22, 2008, 8:55:25 AM8/22/08
to structure...@googlegroups.com
Would you be able to post the snippet that doesn't work?

Brian and Leslie Walk

unread,
Aug 22, 2008, 10:24:39 AM8/22/08
to structure...@googlegroups.com
Basically I am calling the WCF Awards Service from my Web app and I get the 202 - No Default Instance defined for PluginFamily.
I implemented all the code from your post and that works great. Below is a little code snippet of how I have implemented the service, nothing strange about it from what I can see.
 
public
class Awards : IAwards
{
private readonly Data.IAwardRepository _awardRepository;

public Awards(Data.IAwardRepository awardRepository){_awardRepository = awardRepository;}
}
 
I have seen demos that use the global.asax on the web app to load a bootstrapper and use a registry to define the defaults. I find this to be the best solution since it is located in a central location. So I am trying to do the same thing in WCF but I must be missing something.
 
Thanks for the help and let me know if I need to post any more information that would help.

walkf...@gmail.com

unread,
Aug 22, 2008, 8:39:31 PM8/22/08
to structuremap-users
OK. I figured out what I wanted to do.

In the WCF project I created a Service Registry Class. I set of the
Request type and the DefaultConcreteTypes for my IAwards and
IAwardRepository.

public class ServicesRegistry:Registry
{
protected override void configure()
{

ForRequestedType<IAwards>().TheDefaultIsConcreteType<Awards>();


ForRequestedType<IAwardRepository>().TheDefaultIsConcreteType<AwardRepository>();
}
}

In the StructureMapServiceHostFactory Constructor I added an
additional StructureMapConfiguration that adds the ServicesRegistry.

public StructureMapServiceHostFactory()
{
StructureMapConfiguration
.ScanAssemblies()
.IncludeTheCallingAssembly()
.With<DefaultConventionScanner>();

StructureMapConfiguration
.AddRegistry(new ServicesRegistry());
}

Work great now!!!!!

On Aug 22, 9:24 am, "Brian and Leslie Walk" <walkfam...@gmail.com>
wrote:
>  Basically I am calling the WCF Awards Service from my Web app and I get the
> 202 - No Default Instance defined for PluginFamily.
> I implemented all the code from your post and that works great. Below is a
> little code snippet of how I have implemented the service, nothing strange
> about it from what I can see.
>
> public class Awards : IAwards
> {
> private readonly Data.IAwardRepository _awardRepository;
>
> public Awards(Data.IAwardRepository awardRepository){_awardRepository =
> awardRepository;}
>
> }
>
> I have seen demos that use the global.asax on the web app to load a
> bootstrapper and use a registry to define the defaults. I find this to be
> the best solution since it is located in a central location. So I am trying
> to do the same thing in WCF but I must be missing something.
>
> Thanks for the help and let me know if I need to post any more information
> that would help.
>
> On Fri, Aug 22, 2008 at 7:55 AM, Jimmy Bogard <jimmy.bog...@gmail.com>wrote:
>
>
>
> > Would you be able to post the snippet that doesn't work?
>
> > On Fri, Aug 22, 2008 at 4:55 AM, iwalk....@gmail.com <walkfam...@gmail.com
> > > wrote:
>
> >> @Jims suggestion I am posting a question I had from his blog.
>
> >> 'I have implemented all of the changes to my app but I am having an
> >> issue setting up the default instance in WCF. I have seen posts that
> >> setup the interface to a concrete class in code(e.g. a Registry), but
> >> I must be missing something when implementing this in WCF, how do you
> >> do this in a WCF app?'
>
> >> On Jul 29, 10:49 pm, Jimmy Bogard <jimmy.bog...@gmail.com> wrote:
> >> > Yeah, yeah
>
> >> >http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/07/29/integ.
> >> ..
>
> >> > Maybe further down the line, but I definitely ran into some pain where
> >> > I couldn't use the generic goodness, and there weren't System.Type
> >> > equivalents, mostly around the StructureMapConfiguration stuff.  It
> >> > was fun creating the
> >> > IServiceHostFactoryBehaviorInstanceProviderPluginProviderProvider
> >> > implementations, let me tell you...
>
> >> > On Jul 28, 1:22 pm, Jeremy Miller <jeremydmil...@yahoo.com> wrote:
>
> >> > > I can make a small change to make With<T>() act as "use this anywhere
> >> > > in the entire object graph for only this 'BuildSession'"
>
> >> > > It's not actually that big of a change, and if you're hitting this
> >> > > withWCF, someone else will too.
>
> >> > > You know what would be really, really awesome Jimmy?  A blog post on
> >> > > usingWCFwith IoC.- Hide quoted text -
>
> >> > - Show quoted text -- Hide quoted text -

Jimmy Bogard

unread,
Aug 23, 2008, 10:57:15 AM8/23/08
to structure...@googlegroups.com
Funny that you had to specify the explicit types and the DefaultConventionScanner didn't pick them up.  I use the IncludeAssembly method to include specific assemblies by name to include, and the DefaultConventionScanner picks them up that way.

Brian and Leslie Walk

unread,
Aug 23, 2008, 1:03:38 PM8/23/08
to structure...@googlegroups.com
Do you have a little code snippet of how that works? I got my example of the explicit types from part 13 of Rob Conerys MVC Storefront demo.

Jimmy Bogard

unread,
Aug 25, 2008, 8:46:20 PM8/25/08
to structure...@googlegroups.com
StructureMapConfiguration
    .ScanAssemblies()
    .IncludeAssembly("Foo.Bar")
    .With(new DefaultConventionScanner());
Reply all
Reply to author
Forward
0 new messages