JasperFx / lamar

Fast Inversion of Control Tool and Successor to StructureMap
https://jasperfx.github.io/lamar
MIT License
572 stars 119 forks source link

Resolves wrong type with NSwag #107

Closed cocowalla closed 5 years ago

cocowalla commented 5 years ago

I tried adding NSwag.AspNetCore to a web API project that is using Lamar, but it appears to be resolving the wrong type for one of the dependencies, which is resulting in an exception.

When running, it will throw at app.UseSwagger() with:

Unable to cast object of type 'System.Object[]' to type 'System.Collections.Generic.IEnumerable`1[NSwag.AspNetCore.SwaggerDocumentRegistration]'.

   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.AspNetCore.Builder.NSwagApplicationBuilderExtensions.UseSwaggerWithApiExplorerCore(IApplicationBuilder app, Action`1 configure)
   at Microsoft.AspNetCore.Builder.NSwagApplicationBuilderExtensions.UseSwagger(IApplicationBuilder app, Action`1 configure)
   at MyApp.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env) in C:\MyApp\Startup.cs:line 95

So it appears to be resolving Object[] instead of the expected IEnumerable<SwaggerDocumentRegistration>. Not sure if it should matter, but SwaggerDocumentRegistration, which is part of the NSwag assembly, is an internal class. Could be related to #106?

Reproduce To reproduce, start an empty ASP .NET Core API project from the default Visual Studio template, and add these packages:

<PackageReference Include="NSwag.AspNetCore" Version="12.0.4" />
<PackageReference Include="Lamar.Microsoft.DependencyInjection" Version="2.0.0" />

In Program.cs, add the call to .UseLamar(), as usual. In Startup.ConfigureContainer, add:

services.AddSwaggerDocument();

Finally, in Startup.Configure, add:

app.UseSwagger();

When running, it will throw at app.UseSwagger().

jeremydmiller commented 5 years ago

"Not sure if it should matter, but SwaggerDocumentRegistration, which is part of the NSwag assembly, is an internal class." -- it definitely matters. Lamar has to treat internal types very differently. I'll try to reproduce this later in the week

jeremydmiller commented 5 years ago

@cocowalla This one's going to be nasty because of all the damn internals. Lamar really doesn't want you using internal types, and I never realized that that was even common to put things in the IoC container before doing Lamar. Honestly, it'd be way easier to just do a PR to NSwag.

cocowalla commented 5 years ago

This does work with Microsoft's DI library, so i guess it's a common scenario, or they wouldn't have added it - but yeah, it does seem odd to rely on DI for internal types...

jeremydmiller commented 5 years ago

They're the ones who cause this issue in the first place. StructureMap handles it fine too. Anything that uses compiled Expressions can deal with that. My concept for Lamar was specifically to avoid having to do that 'cause it's so damn nasty to work with.

cocowalla commented 5 years ago

The NSwag author agreed and changed the internal type to public, so this specific issue is probably resolved now (will test it on Monday).

Not sure if you want to keep this open and think about a strategy for resolving internal types, or if you prefer Lamar to be opinionated and not handle this anti-pattern? (if it's the latter, I fully understand why)

jeremydmiller commented 5 years ago

I think this is more or less resolved

antonioortizpola commented 5 years ago

I think this is not resolved, it is related with #135, from what i understand this will be related to #136.