How to use Auto Registration and Type Scanning in Structuremap

2.3k Views Asked by At

In my solution I have three projects like this. enter image description here

I copy Common.dll and Service.dll in a folder like d:\libs and use the below code with type scan

 ObjectFactory.Initialize(x =>
           {
              x.Scan(xx =>
               {
                   xx.AssembliesFromPath(@"d:\libs");
                   xx.LookForRegistries();
               });
           });
//I have PersonService that implement IPersonService
namespace Common
{
    public interface IPersonService
    {
        string SayHello(string name);
    }
}
namespace Services
{
    public class PersonService : IPersonService
    {
        public string SayHello(string name)
        {
            return string.Format("Hello {0}", name);
        }
    }
}

After Initialize my dependencies when I want get instance from IPerson I get this error

  var personService = ObjectFactory.GetInstance<IPersonService>();

{"No default Instance is registered and cannot be automatically determined for type 'Common.IPersonService'\r\n\r\nThere is no configuration specified for Common.IPersonService\r\n\r\n1.) Container.GetInstance(Common.IPersonService)\r\n"}

3

There are 3 best solutions below

2
On BEST ANSWER
  • Add xx.WithDefaultConventions(); as well.
  • And when you are designing a plugin system by using StructureMap, the host project shouldn't have a reference to any of the plugins. Only the interface/contract plugin should be referenced and this assembly shouldn't be copied to d:\libs folder. In other words, the current application domain shouldn't have 2 instances of any assemblies. So if you want to use IPersonService interface in the host program directly, add a reference to Common.dll and don't copy it to d:\libs folder to avoid duplication. And now the host project shouldn't have a reference to Services.dll too.
0
On

You can use the WithDefaultConventions() in your call to Scan which will internally use a DefaultConventionScanner.

You can read the source code or look at the documentation but it does this:

var interfaceName = "I" + concreteType.Name;
return concreteType.GetInterfaces().FirstOrDefault(t => t.Name == interfaceName);

During a default convention scan, each concrete type scanned will look for the first interface of the class name preceded by the letter "I". Therefore, while scanning, IFooService with be automatically registered and assigned if FooService is found during the scan, therefore allowing you to not have to explicitly say

For<IFooService>().Use<FooService>()

The exception you are seeing will always be thrown when there is no registered concrete implementation for the type you requested.

0
On

The types you expected to be registered are not because you are scaning with xx.LookForRegistries() which looks for StructureMap registries (you can read more about registries here - http://structuremap.github.io/registration/registry-dsl/). If you create such registries with proper registrations then SM will find them and registeres.

As already mentioned the altrernative is to use xx.WithDefaultConventions(). Take a look at this edge case when using default convention the expected type was not registered - https://stackoverflow.com/a/27449018/4336786