Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StructureMap resolve a dependency across projects

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.

like image 630
Lotok Avatar asked Apr 06 '15 11:04

Lotok


1 Answers

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 putted scan.lookforregistries which will look for registry in each project. Here I have putted just name of assembly. You need to replace with your assemblies.

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

like image 161
Jalpesh Vadgama Avatar answered Oct 24 '22 17:10

Jalpesh Vadgama