Please help with ScanAssemblies

7 views
Skip to first unread message

jdc

unread,
Sep 11, 2008, 10:17:16 AM9/11/08
to structuremap-users
I'm trying to understand Registry and ScanAssemblies. Here's what
I've put together to test with:

Web application with a simple "Hello World" type page.
Web app references Core assembly.
Core assembly contains IWidget interface containing nothing but a Name
property.
Three additional assemblies "Red", "Green", and "Blue" contain
RedWidget, BlueWidget, and GreenWidget which are very skeletal
implementations of IWidget that set the Name property to a name passed
in through the constructor.

So, each color assembly has a registry that looks like this:

public class RedRegistry : StructureMap.Configuration.DSL.Registry
{
protected override void configure()
{

StructureMap.StructureMapConfiguration.AddInstanceOf<CoreStuff.IWidget>()
.UsingConcreteType<RedWidget>()
.WithName("RedWidget")
.WithProperty("name").EqualTo("Red Widget");
}
}

To use a widget in the web app I use code like this:

CoreStuff.IWidget redWidget =
StructureMap.ObjectFactory.GetNamedInstance<CoreStuff.IWidget>("RedWidget");

So, if I put this in my app startup things work:

StructureMap.StructureMapConfiguration.AddRegistry(new
RedNamespace.RedRegistry());
StructureMap.StructureMapConfiguration.AddRegistry(new
GreenNamespace.GreenRegistry());
StructureMap.StructureMapConfiguration.AddRegistry(new
BlueNamespace.BlueRegistry());

I was under the impression I could do this, but it doesn't seem to
work:

StructureMap.StructureMapConfiguration.ScanAssemblies()
.IncludeAssemblyContainingType<RedNamespace.RedRegistry>()
.IncludeAssemblyContainingType<GreenNamespace.GreenRegistry>()
.IncludeAssemblyContainingType<BlueNamespace.BlueRegistry>();

Whenever I try to get a widget from the container, I get the "Could
not find Instance named RedWidget for plugin type CoreStuff.IWidget"
message.

Actually, what I'd rather do is something like this to get all
assemblies that happen to contain IWidget implementations:

StructureMap.StructureMapConfiguration.ScanAssemblies()
.IncludeAssemblyContainingType<CoreStuff.IWidget>()

but I'd be happy at this point just to get the simple case where I
know the registries in advance.

Any idea what I'm missing? I've done Google searches out the wazoo
without any luck so far.

jdc

unread,
Sep 11, 2008, 11:28:30 AM9/11/08
to structuremap-users
A few other things I tried... For simplification, I removed the
"name" parameter so the widgets have a parameterless constructor. I
also changed the configuration method of the registries to look like
this:


StructureMap.StructureMapConfiguration.BuildInstancesOf<IWidget>()
.TheDefault.Is.OfConcreteType<GreenWidget>();

I tried this in my startup routine also - which resulted in all of the
registries being called as I could see through the debugger:

StructureMap.ObjectFactory.Configure(registry =>
registry.ScanAssemblies()
.IncludeAssemblyContainingType<RedNamespace.RedRegistry>()
.IncludeAssemblyContainingType<GreenNamespace.GreenRegistry>()
.IncludeAssemblyContainingType<BlueNamespace.BlueRegistry>());

Still get an error 202 from StructureMap when I try to do a
GetInstance<IWidget>() though. Even though I watched it in the
debugger run through those BuildInstancesOf calls at startup.

Chad Myers

unread,
Sep 11, 2008, 11:31:49 AM9/11/08
to structure...@googlegroups.com
Try something like this:

protected override void configure()
{
      ForRequestedType<CoreStuff.IWidget>().TheDefaultIsConcreteType<RedWidget>()...

jdc

unread,
Sep 11, 2008, 11:38:45 AM9/11/08
to structuremap-users
That didn't work either. After my configuration methods run (and I've
whittled it down to just one) the ObjectFactory.WhatDoIHave method
returns this:

===========================================================================================================
Configuration Sources:

0) Registry: StructureMap.Configuration.DSL.Registry,StructureMap
1) Registry: StructureMap.Configuration.DSL.Registry,StructureMap


===================================
PluginType Name Description
===================================


Then if I re-run (after the 202 exception, but without restarting the
app) I get this:

===========================================================================================================
Configuration Sources:

0) Registry: StructureMap.Configuration.DSL.Registry,StructureMap
1) Registry: StructureMap.Configuration.DSL.Registry,StructureMap


====================================================
PluginType Name Description
----------------------------------------------------
CoreStuff.IWidget,CoreStuff
Built by: StructureMap.Pipeline.BuildPolicy

====================================================

This is confusing the hell out of me. Do I need the configuration XML
file or attributes? I was under the impression that using
ScanAssemblies with the Registry classes I wouldn't need those.

jdc

unread,
Sep 11, 2008, 11:46:54 AM9/11/08
to structuremap-users
Ok, I'm getting closer. If, within the Registry configure method, I
use something like this:

ObjectFactory.SetDefault<IWidget, GreenWidget>()

then I can instantiate one later. It's like calling methods on
StructureMapConfiguration doesn't apply to ObjectFactory.

Jeremy D. Miller

unread,
Sep 11, 2008, 11:50:38 AM9/11/08
to structure...@googlegroups.com
STOP!

Don't ever make any calls to ObjectFactory within a Registry.  I think I'm killing off that SetDefault method right now because it can only cause problems.

Give me the lunch hour and I'll respond to the ScanAssemblies question.
 
Jeremy D. Miller
The Shade Tree Developer
jeremy...@yahoo.com
Message has been deleted
Message has been deleted

jdc

unread,
Sep 12, 2008, 9:08:59 AM9/12/08
to structuremap-users
I banged around on this a little more yesterday evening and still no
luck. I think I'm using the latest trunk (last update I pulled down
was from September 2). Maybe I'm misunderstanding what ScanAssemblies
is supposed to do?

Jimmy Bogard

unread,
Sep 12, 2008, 9:11:31 AM9/12/08
to structure...@googlegroups.com
Don't use still have to use a scanner?  I think you might still need to have the .With<DefaultConventionScanner>() part.

On Thu, Sep 11, 2008 at 9:17 AM, jdc <jdcru...@spiffworks.com> wrote:

jdc

unread,
Sep 12, 2008, 9:27:15 AM9/12/08
to structuremap-users
I did have some success using a scanner, but I'd rather avoid that.
What I'm looking for is some way to drop a DLL into the directory and
have the existing call to ScanAssemblies find the Registry within it
and fire off the configure method. I can actually get that far. I
step through in the debugger and see the configure method running.
The trouble is, the registrations I do within that method don't
"stick". However, if I do a StructureMapConfiguration.AddRegistry(new
TheRegistry()) for each one, then it works. Of course then I'm back to
knowing in advance what my registries are...

I suppose I could try creating an ITypeScanner that, when it finds
something assignable to IRegistry, calls
StructureMapConfiguration.AddRegistry on it. I'll probably try that
next.

I was just under the impression that ScanAssemblies was supposed to do
that already.

Jeremy D. Miller

unread,
Sep 12, 2008, 9:54:25 AM9/12/08
to structure...@googlegroups.com
ScanAssemblies has to be explicitly told which assemblies to scan.  I've always been leery of any kind of behavior that you wouldn't expect.

You've got a couple options, but they both involve writing your own code:

1.) Set aside an "extensions" folder of some type directly under the main application folder.  In the bootstrapping code, find all the assembly files in that directory, and add each to ScanAssemblies().AddAssembly( assembly name).  This is the approach that my team is going to take for our extensibility strategy, but we aren't going to work on that until at least October.

2.) Go with an Xml file at an expected location that lists the assemblies to load


ScanAssemblies will pick up any registry classes in assemblies (plus the attribute configuration, but I'd recommend the Registry approach), but it has to be told which assemblies to load and scan.
----- Original Message ----
From: jdc <jdcru...@spiffworks.com>
To: structuremap-users <structure...@googlegroups.com>
Sent: Friday, September 12, 2008 8:27:15 AM
Subject: [sm-users] Re: Please help with ScanAssemblies


jdc

unread,
Sep 12, 2008, 10:05:43 AM9/12/08
to structuremap-users
Thanks Jeremy. The problem I'm having though isn't that the
registries aren't being scanned. I can watch in the debugger that the
configure methods are called. However, the statements in them don't
seem to have any effect. I still get 202 errors when I try
GetInstance. It does work if I used
StructureMapConfiguration.AddRegistry on each of them though. In both
cases I can watch through the debugger and see configure getting
called on each registry, but when it's kicked off from ScanAssemblies
the configuration doesn't stick.

I also noticed that using ScanAssemblies, the actual running of the
configure methods is delayed until the first call to GetInstance.
Probably because ScanAssemblies is really just creating an
expression. Is it possible that my ObjectFactory is getting into some
state where it doesn't allow changes by the time the actual scan runs?

Chad Myers

unread,
Sep 12, 2008, 10:15:38 AM9/12/08
to structure...@googlegroups.com
So you're looking for like a start-up plug-in discovery type functionality?

-c

-----Original Message-----
From: structure...@googlegroups.com
[mailto:structure...@googlegroups.com] On Behalf Of jdc
Sent: Friday, September 12, 2008 8:27 AM
To: structuremap-users
Subject: [sm-users] Re: Please help with ScanAssemblies

jdc

unread,
Sep 12, 2008, 10:25:30 AM9/12/08
to structuremap-users
I was just trying to work through your example at
http://www.lostechies.com/blogs/chad_myers/archive/2008/07/17/structuremap-medium-level-usage-scenarios.aspx.
Assuming I could get that working, I was going to try something like
what Jeremy mentioned about creating a special directory for
assemblies to be auto-scanned for registries then use some reflection
magic to add each one to the scan.

Trouble is, I can't even get the simple case to work. Scan assemblies
seems to have no trouble finding the registries and running their
configure methods. It's just that any configuration done by those
registries doesn't seem to actually happen. Only adding the registry
directly with StructureMapConfiguration.AddRegistry actually works.

Jeremy D. Miller

unread,
Sep 12, 2008, 10:38:27 AM9/12/08
to structure...@googlegroups.com
Any chance you can send me the code?  That functionality has quite a bit of unit test coverage, so I think there's something else going on.
----- Original Message ----
From: jdc <jdcru...@spiffworks.com>
To: structuremap-users <structure...@googlegroups.com>
Sent: Friday, September 12, 2008 9:05:43 AM
Subject: [sm-users] Re: Please help with ScanAssemblies


jdc

unread,
Sep 12, 2008, 10:57:45 AM9/12/08
to structuremap-users
Sure thing. I sent the project to your Yahoo account. Thanks for
having a look at this.

On Sep 12, 9:38 am, "Jeremy D. Miller" <jeremydmil...@yahoo.com>
wrote:
> Any chance you can send me the code?  That functionality has quite a bit of unit test coverage, so I think there's something else going on.
>
>  Jeremy D. Miller
> The Shade Tree Developer
> jeremydmil...@yahoo.com
>
>
>
> ----- Original Message ----
> From: jdc <jdcrutch...@spiffworks.com>
> To: structuremap-users <structure...@googlegroups.com>
> Sent: Friday, September 12, 2008 9:05:43 AM
> Subject: [sm-users] Re: Please help with ScanAssemblies
>
> Thanks Jeremy.  The problem I'm having though isn't that the
> registries aren't being scanned.  I can watch in the debugger that the
> configure methods are called.  However, the statements in them don't
> seem to have any effect.  I still get 202 errors when I try
> GetInstance.  It does work if I used
> StructureMapConfiguration.AddRegistry on each of them though.  In both
> cases I can watch through the debugger and see configure getting
> called on each registry, but when it's kicked off from ScanAssemblies
> the configuration doesn't stick.
>
> I also noticed that using ScanAssemblies, the actual running of the
> configure methods is delayed until the first call to GetInstance.
> Probably because ScanAssemblies is really just creating an
> expression.  Is it possible that my ObjectFactory is getting into some
> state where it doesn't allow changes by the time the actual scan runs?- Hide quoted text -
>
> - Show quoted text -

jdc

unread,
Sep 15, 2008, 2:16:41 PM9/15/08
to structuremap-users
FYI for anyone having a similar problem:

Jeremy was good enough to have a look at my code and point me in the
right direction. Apparently I should NOT have been doing this from
within a registry:

StructureMap.StructureMapConfiguration.AddInstanceOf<CoreStuff.IWidget>()
.UsingConcreteType<RedWidget>()
.WithName("RedWidget")
.WithProperty("name").EqualTo("Red Widget");

I should have done this:

BuildInstancesOf<CoreStuff.IWidget>()
.TheDefault.Is.OfConcreteType<RedWidget>()
.WithName("RedWidget")
.WithProperty("name").EqualTo("Red Widget");

Thanks to everyone that helped track this down.

Jimmy Bogard

unread,
Sep 15, 2008, 7:22:40 PM9/15/08
to structure...@googlegroups.com
Obsoleting the SMC stuff should fix this too...
Reply all
Reply to author
Forward
0 new messages