4

So I have an issue with the latest StructureMap (v4.6.1) in a ASP.Net Core Web API application:

Here is what I have:

  • Web API Project
  • Interface Project
  • Assembly A (Implements subset of interfaces from the Interface Project)
  • Assembly B (Implements the remainder of the interfaces defined in the Interface Project)

Assembly A uses standard conventions for implementing the interfaces i.e. interface ISomething is implemented in a class called Something.

Assembly B also implements several generic interfaces defined in Interface project. There is no special convention used in naming these implementations.

Both Assembly A and Assembly B are built and deployed in the root folder from which the Web API Project executes. The Web API project does NOT reference any of the underlying assemblies (Interface, Assembly A and Assembly B).

In the Web API project Startup.cs I have the following:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    var container = new Container();
    container.Configure(c =>
    {
        c.Scan(scanner =>
        {
            scanner.AssembliesFromApplicationBaseDirectory();
            scanner.WithDefaultConventions();
        });

        c.Populate(services);
    });
    return container.GetInstance<IServiceProvider>();
}

When I check for the registered assemblies the concrete types that are using the default conventions are not picked up by the scanner even thou the assemblies are present at runtime.

What I would like to achieve is the following:

  • Have the scanner scan the directory and bind the classes it knows how to bind using standard conventions
  • For the rest of the interfaces (especially the generic interfaces not following any specific conventions) to use a registry defined in the assembly where the concrete type is defined
  • Essentially, I would like to treat my underlying architecture as a plugin to the executing environment i.e. be able to dynamically add assemblies that implement interfaces and have the DI container register them either by using default conventions or a registry class I have defined in an assembly.

Note: I also tried adding the scanner.LookForRegistries() to the scanner but to no avail.

Note #2: There are also other assemblies containing interfaces which the API references that are implemented elsewhere in another assemblies. Those are being picked up by the scanner but the dependencies of those dependencies are not.

Toni Kostelac
  • 351
  • 3
  • 17
  • It could be that the scanner finds A and B but can’t load all assemblies they reference. Try hooking the AssemblyResolve event to see what it’s trying to load. Also ensure that the assemblies in the base dir aren’t on/from a share (or otherwise tagged as being from an insecure zone) which might prevent their loading. – Zastai Feb 09 '18 at 16:47
  • I've hooked into the event, and it shows all of my assemblies being scanned, but when it comes to picking up the interfaces and implementations and adding them to the container it does nothing. Granted there are a few generics in there which will need registries but the registries are there and it's not picking them up, and the application blows up with Structure Map complaining about the IComponent not being able to map it to a concrete implementation – Toni Kostelac Feb 15 '18 at 16:52

1 Answers1

0

I think the problem is not in Structuremap but because this is ASP.NET application and not all assemblies are loaded at run time immediately I solved this problem by

 var referencedAssemblies =BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToList();

This method will return all assemblies and then you can use them to scan with IoC container!

Sergey K
  • 4,071
  • 2
  • 23
  • 34
  • This is a subdependency, to which the ASP.NET has no direct dependency. Would this still work given that constraint? – Toni Kostelac Feb 15 '18 at 16:50
  • What do you mean subdependency? method above will return all referenced assemblies in project and than you can scan them – Sergey K Feb 15 '18 at 20:43
  • There is no explicit reference between the two assemblies. It's like a plugin. – Toni Kostelac Feb 16 '18 at 09:16
  • Yes I understand now, and yes it will work. In my case I had the same situation, and as you wrote you have explicit dependency between, Interface assembly and Implementation in assemblies in A and B – Sergey K Feb 16 '18 at 17:01
  • I won't be able to test this until Monday – Toni Kostelac Feb 16 '18 at 22:48
  • After playing around with this, it didn't solve my issue. – Toni Kostelac Feb 20 '18 at 09:41
  • Ok so I figured it out why this isn't working. The IIS we're using is preventing structure map from scanning the directory. I wrote a workaround to get past this. – Toni Kostelac Mar 05 '18 at 13:17
  • @ToniKostelac I has the same issue if you solved this problem, please share your answer. – Amir Jan 27 '22 at 08:12
  • @Amir The issue was that IIS was blocking the IoC from scanning the directory as I mentioned above. Unfortunately I no longer work at that company so I can't find the workaround that I used at the time. Sorry that I can't be of more help. – Toni Kostelac Jan 28 '22 at 12:30