StructureMap resolve a dependency across projects
Asked Answered
M

1

5

My solution has 4 projects in it

  1. UI
  2. Infrastructure
  3. Entities
  4. Tests

All of the code-first database setup and the structuremap setup sits within the infrastructure project. The UI is ASP.NET MVC5. The infrastructure project also hosts some WebService implementations.

In the UI Project has some classes which act as a layer between the Controllers and the External WebServices. For example:

UI.Services.MappingService.cs will be using methods in Infrastructure.ExternalWebServices.MappingWebService.cs

Until now there has been no problems, the interface names all match the concrete class names, so structuremap resolves them correctly. However, there is now a requirement to make changes and implement multiple concrete classes from one of the service interfaces.

The infrastructure project cannot reference the UI as it creates a circular dependency. Using the Mapping example, I would need

UI.Services.Interfaces.IMappingService to have different concretes, structuremap would resolve the correct one either by logic in a Registry file or a factory class. The problem being the registry files are in the infrastructure project which is not aware of the UI so For(...).Use(...) is not possible.

If I move the Interfaces out to the Entities project, it can then see them but that would also involve moving the concrete classes out which would break many references and require a hell of a lot of moving files to fix. The entire service layer in UI plus quite a few view models would need to move out to the Entities project to make that possible.

Is there an easier way? I am no DI/StructureMap expert so I want to be sure I am not just making life harder.

Monkey answered 6/4, 2015 at 11:21 Comment(2)
Is there a problem to move ioc container to asp.net mvc layer? and left just interface in infrastructure (if needed)Lettyletup
You could put a registry in your UI layer to control registrations which are more specific to the UI layer. Also, you can Scan(x => x.AddAllTypesOf<IMappingService>()).Misspend
A
10

You can do with registry features of structuremap.

First you need to create registry in each project like below.

public class InfrastructureRegistry : Registry
{
    public InfrastructureRegistry ()
    {
        Scan(scan =>
        {
            scan.TheCallingAssembly();
            scan.WithDefaultConventions();
           
        });

        //any spefic implementation   
    }
}              

Then you need to create your container like below:

return new Container(
            x => x.Scan
                   (
                       scan =>
                       {
                           scan.Assembly("YourProject.UI");
                           scan.Assembly("YourProject.Infrastructure");
                           scan.Assembly("Your.Entities");
                           scan.WithDefaultConventions();
                           scan.LookForRegistries();
                       }
                   )
          );

Here I have put scan.lookforregistries which will look for registry in each project. Here I have put just the name of assembly. You need to replace with your assemblies.

So you can access that for each project and it will wire up all the things.

Amalgamate answered 6/4, 2015 at 12:50 Comment(2)
Brilliant, saved me a potentially huge refactor. Thanks very muchMonkey
Related on how to use this approach to avoid the need to reference infrastructure from your UI projects: ardalis.com/…Aluminous

© 2022 - 2024 — McMap. All rights reserved.