views:

169

answers:

2

Hi. I am very new to StructureMap and am getting the following error:

StructureMap Exception Code: 202 No Default Instance defined for PluginFamily Company.ProjectCore.Core.IUserSession, Company.ProjectCore, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

It seems to be hitting the first interface instance on compile and then throws the above error:

private readonly IUserSession _userSession;

public SiteMaster()
{
  _userSession = ObjectFactory.GetInstance<IUserSession>(); // ERROR THROWN HERE
  ...
}

For what it is worth, I have the PluginFamily reference above all of interfaces:

[PluginFamily("Default")]
public interface IUserSession

Below is my entire StructureMap.config

<StructureMap>
  <Assembly Name="Company.ProjectWeb" />
  <Assembly Name="Company.ProjectCore" />
  <!--
  Use DefaultKey="Default" for standard cache 
  or DefaultKey="MemCached" for memcached cache.
  -->
  <PluginFamily
      Assembly="Company.ProjectCore"
      Type="Company.ProjectCore.Core.ICache"
      DefaultKey="MemCached" />
  <!--
  Use DefaultKey="Default" for sending the email
  in real time through the configured mail server 
  or use DefaultKey="MailQueue" to send the mail
  in batches through another process
  -->
  <PluginFamily
      Assembly="Company.ProjectCore"
      Type="Company.ProjectCore.Core.IEmailService"
      DefaultKey="MailQueue" />
  <!--
  Use DefaultKey="Default" for standard cache 
  or DefaultKey="UserSession" for memcached cache.
  -->
  <PluginFamily
      Assembly="Company.ProjectCore"
      Type="Company.ProjectCore.Core.IUserSession"
      DefaultKey="UserSession" />
  <!--
  Use DefaultKey="Default" for standard cache 
  or DefaultKey="Redirector" for memcached cache.
  -->
  <PluginFamily
      Assembly="Company.ProjectCore"
      Type="Company.ProjectCore.Core.IRedirector"
      DefaultKey="Redirector" />
  <!--
  Use DefaultKey="Default" for standard cache 
  or DefaultKey="Navigation" for memcached cache.
  -->
  <PluginFamily
      Assembly="Company.ProjectCore"
      Type="Company.ProjectCore.Core.INavigation"
      DefaultKey="Navigation" />

Any suggestions? Thanks.

+1  A: 

The config looks correct to me at first glance. Are you calling ObjectFactory.Initialize before the code you posted runs?

I don't use attributes or config files myself (anymore), but I don't think you need to use both.

Also, is there a reason you want to use attributes and/or XML in the first place? You can configure your instances via code with StructureMap via a fluent interface, and IMHO this is a better way of doing it (unless you need to swap implementations in production, but even then there are other options).

See also: http://structuremap.github.com/structuremap/ConfiguringStructureMap.htm

Update After Comments

Ok, so I downloaded the app, but can't get it to run, and can't really take the time to troubleshoot. So I'm sorry if I can't help any further.

However I did poke around the code very briefly, and I can tell you definitively that some of the code I saw for using IOC/DI is very disturbing. Unless this is starter code that the book then shows you how to refactor, I would not recommend this as a source for learning the IOC pattern or StructureMap.

Here is an example of bad code:

public AccountService()
{
    _accountRepository = ObjectFactory.GetInstance<IAccountRepository>();
    _permissionRepository = ObjectFactory.GetInstance<IPermissionRepository>();
    _userSession = ObjectFactory.GetInstance<IUserSession>();
    _redirector = ObjectFactory.GetInstance<IRedirector>();
    _email = ObjectFactory.GetInstance<IEmail>();
    _profileService = ObjectFactory.GetInstance<IProfileService>();
    _webContext = ObjectFactory.GetInstance<IWebContext>();
    _friendService = ObjectFactory.GetInstance<IFriendService>();
}

To me this a clear Global Service Locator anti-pattern. Even barring that, it is violating one of the core principles of IOC, which is that dependencies should be explicit.

Your application should have few (or even one, if possible) call to ObjectFactory.GetInstance(), and from that point on, all dependencies should be handled through the framework as constructor arguments.

So the constructor for Account Service would look something like:

public AccountService(IAccountRepository accountRepository) 
    {
        //all arguments (not just account repo) would be passed into the ctor
        //you also want to check for null for all arguments
        _accountRepository = accountRepository;
    }

(also note that 8 arguments is LIKELY a sign that this class has too many responsibilities)

It's really too much to get into in a single post, but I would recommend finding a better source for learning the pattern and tool.

Phil Sandler
Phil, thanks for the response. I downloaded and application that helps me get up and running with SM. I tried to do a search on ObjectFactory.Initialize and came up with nothing. When (and where) should this be called? Thanks again.
Code Sherpa
It should be called when your application starts up. There may be other ways of initializing SM, possibly older or newer ways then the version I am currently using. Want to post a link to the app you used as a starting point?
Phil Sandler
Phil - Thanks again. I have been following the StructureMap instructions using Andrew Siemer's ASP.NET 3.5 Social Networking book. The code is downloadable from his publisher's site here: https://www.packtpub.com/code_download/1200Let me know if you need anything else. Thanks a ton for your feedback.
Code Sherpa
That's a big download--not sure if I can get it (trying now). Is the downloaded code not working, or are you creating your own version that's not working?
Phil Sandler
No, the downloaded code works. I ran it raw and his project compiled. All I did, really, is change the project name and use ReSharper to touch things up. Now, when I run it I get the 202 error but for the life of me, I don't know why. I made no changes whatsoever to SM.
Code Sherpa
But, I see your point. I'll try lining up my slightly altered project with the initially downloaded project to see if I can identify any differences.
Code Sherpa
updated answer based on the source code.
Phil Sandler
Thanks a ton Phil. Your comments were seriously helpful (and I really appreciate your taking the time to look at the project). Michal's advice led to the solution but I up-voted you for all the useful feedback. Thanks again.
Code Sherpa
A: 

The author of StructureMap has discouraged the use of the XML declaration. Why not declare it with code, like this:

ObjectFactory.Initialize(x => 
    {
        x.For<ICache>().Use<MemCached>();
        x.For<IEmailService>().Use<MailQueue>();
        x.For<IUserSession>().Use<UserSession>();
        x.For<IRedirector>().Use<Redirector>();
        x.For<INavigation>().Use<Navigation>();
    });

That way you won't have to guess about whether things are wired correctly. It's also much easier to maintain and less code.

Michael Hedgpeth
Michael - Thanks! That worked brilliantly. Seems the SM architecture that I am doing my learning from is a bit dated. Much appreciated.
Code Sherpa