c++asp.net-coredependency-injectioncoreclr

Asp.Net Core Dependency Injection doesn't work, if it is started from unmanaged/native


First i try to explain the story.

I wanted to extend an C++/MFC application with REST-APIs, and decided to use for this purpose Asp.Net-Core 5 in a library by bridging it to unmanaged code with C++/CLI library. (having a separete ASP application is doubled expenditure, and needed to be rewritten all the logic in C#. in that regard RESTful-Server should be in same process implemented.)

Asp-Host is started in that way; C++/MFC -> C++/CLI -> ASP-Library (ASP referenced in CLI, CLI referenced in Native)

First problem was; by building the host Microsoft.Extensions.Hosting.Abstractions-Assembly could not be resolved. I found that, "My CLI Library".runtimeconfig.json has wrong framework reference and causes it not to be resolved. That means generated runtimeconfig.json is wrong. After every build it has to be manually with AspNetCore instead of NETCore corrected. (Done in PostBuildEvent)

Next problem; during the ASP-Host build, ASP could not resolve "My ASP Library.dll"-Assembly (in reflection). This problem solved by OnAssemblyResolve event by giving the right path. I'm not sure whether it is correct solution. Because AppDomain.BaseDirectory is an empty string, maybe it is the cause of it, that the library could not found.

In AssemblyResolve event;

Assembly::LoadFrom(assemblyFile)

Finally i could start the server, and it works. Then needed to use dependency injection, and my service could not be resolved from the controller. Then i used my ASP-Library in another C#-project to test and it works... i'm sure that it doesn't work if the entry point of process is in unmanaged code.

public interface IServerImpl
{
  void OnFail(String msg);
}

public class CServerImpl : IServerImpl
{
  public void OnFail(String msg)
  {
  }
}

... in Startup

public void ConfigureServices(IServiceCollection services)
{
  services.AddSingleton<IServerImpl, CServerImpl>();

  services.AddControllers();
}

... Controller

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
  private readonly ILogger<WeatherForecastController> _logger;
  private readonly IServerImpl _serverImpl;

  public WeatherForecastController(ILogger<WeatherForecastController> logger, IServerImpl serverImpl)
  {
    _logger = logger;
    _serverImpl = serverImpl;
  }
  ...
}

Is there any workaround to have it working? Are those problems bug in Asp.Net-Core or what am i doing wrong?

Thanks in advance


Solution

  • The problem has been solved. Assembly resolving event with Assembly.LoadFrom() causes my ASP-assembly to be loaded (or mapped) twice. Loading it in different assembly-load-context means that, doubled Types, static variables and so on. In that regard my registered IServerImpl service searched in the controller with another IServerImpl type. Type names are identical, but not the same.

    For more information see technical challenges: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.loader.assemblyloadcontext?view=net-5.0

    Another issue on GitHub: https://github.com/dotnet/runtime/issues/39783

    In assembly resolve event, i'm returning now the loaded assembly like that, instead of loading it again;

    AppDomain.CurrentDomain.GetAssemblies()
              .SingleOrDefault(asm => asm.FullName.StartsWith(args.Name.Split(',')[0] + ","))
    

    still wellcome answers which clarifies "why my ASP-assembly not found from the framework?"