Asp.Net 如果从 unmanaged/native 开始,核心依赖注入不起作用
Asp.Net Core Dependency Injection doesn't work, if it is started from unmanaged/native
首先我试着解释一下这个故事。
我想用 REST-API 扩展 C++/MFC 应用程序,并决定为此目的使用库中的 Asp.Net-Core 5,方法是使用 C++/CLI 库将其桥接到非托管代码。 (有一个单独的 ASP 应用程序是双倍的支出,需要用 C# 重写所有逻辑。在这方面 RESTful-服务器应该在同一个进程中实现。)
Asp-Host是这样启动的; C++/MFC -> C++/CLI -> ASP-库(ASP 在 CLI 中引用,CLI 在 Native 中引用)
第一个问题是;通过构建主机 Microsoft.Extensions.Hosting.Abstractions-无法解析程序集。我发现,“My CLI Library”.runtimeconfig.json 有错误的框架引用,导致无法解析。这意味着生成的 runtimeconfig.json 是错误的。每次构建后,都必须手动使用 AspNetCore 而不是 NETCore 进行更正。 (在 PostBuildEvent 中完成)
下一题;在 ASP-Host 构建期间,ASP 无法解析“My ASP Library.dll”-Assembly(反射)。通过提供正确的路径,OnAssemblyResolve 事件解决了这个问题。我不确定这是否是正确的解决方案。因为 AppDomain.BaseDirectory 是一个空字符串,可能是找不到库的原因。
在 AssemblyResolve 事件中;
Assembly::LoadFrom(assemblyFile)
我终于可以启动服务器了,它可以工作了。然后需要使用依赖注入,而我的服务无法从控制器解析。
然后我在另一个 C# 项目中使用我的 ASP-Library 进行测试并且它有效......
如果进程的入口点在非托管代码中,我确定它不起作用。
public interface IServerImpl
{
void OnFail(String msg);
}
public class CServerImpl : IServerImpl
{
public void OnFail(String msg)
{
}
}
...在启动中
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IServerImpl, CServerImpl>();
services.AddControllers();
}
...控制器
[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;
}
...
}
是否有任何解决方法可以使其正常工作?这些问题是 Asp.Net-Core 中的错误还是我做错了什么?
提前致谢
问题已解决。使用 Assembly.LoadFrom()
的程序集解析事件导致我的 ASP-程序集被加载(或映射)两次。在不同的程序集加载上下文中加载它意味着,加倍类型、静态变量等。在这方面,我注册的 IServerImpl
服务在控制器中搜索了另一种 IServerImpl
类型。类型名称相同,但不相同。
有关更多信息,请参阅技术挑战:https://docs.microsoft.com/en-us/dotnet/api/system.runtime.loader.assemblyloadcontext?view=net-5.0
关于 GitHub 的另一个问题:https://github.com/dotnet/runtime/issues/39783
在程序集解析事件中,我现在像这样返回加载的程序集,而不是再次加载它;
AppDomain.CurrentDomain.GetAssemblies()
.SingleOrDefault(asm => asm.FullName.StartsWith(args.Name.Split(',')[0] + ","))
仍然是 wellcome 的回答,阐明了“为什么我的 ASP-assembly 没有从框架中找到?”
首先我试着解释一下这个故事。
我想用 REST-API 扩展 C++/MFC 应用程序,并决定为此目的使用库中的 Asp.Net-Core 5,方法是使用 C++/CLI 库将其桥接到非托管代码。 (有一个单独的 ASP 应用程序是双倍的支出,需要用 C# 重写所有逻辑。在这方面 RESTful-服务器应该在同一个进程中实现。)
Asp-Host是这样启动的; C++/MFC -> C++/CLI -> ASP-库(ASP 在 CLI 中引用,CLI 在 Native 中引用)
第一个问题是;通过构建主机 Microsoft.Extensions.Hosting.Abstractions-无法解析程序集。我发现,“My CLI Library”.runtimeconfig.json 有错误的框架引用,导致无法解析。这意味着生成的 runtimeconfig.json 是错误的。每次构建后,都必须手动使用 AspNetCore 而不是 NETCore 进行更正。 (在 PostBuildEvent 中完成)
下一题;在 ASP-Host 构建期间,ASP 无法解析“My ASP Library.dll”-Assembly(反射)。通过提供正确的路径,OnAssemblyResolve 事件解决了这个问题。我不确定这是否是正确的解决方案。因为 AppDomain.BaseDirectory 是一个空字符串,可能是找不到库的原因。
在 AssemblyResolve 事件中;
Assembly::LoadFrom(assemblyFile)
我终于可以启动服务器了,它可以工作了。然后需要使用依赖注入,而我的服务无法从控制器解析。 然后我在另一个 C# 项目中使用我的 ASP-Library 进行测试并且它有效...... 如果进程的入口点在非托管代码中,我确定它不起作用。
public interface IServerImpl
{
void OnFail(String msg);
}
public class CServerImpl : IServerImpl
{
public void OnFail(String msg)
{
}
}
...在启动中
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IServerImpl, CServerImpl>();
services.AddControllers();
}
...控制器
[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;
}
...
}
是否有任何解决方法可以使其正常工作?这些问题是 Asp.Net-Core 中的错误还是我做错了什么?
提前致谢
问题已解决。使用 Assembly.LoadFrom()
的程序集解析事件导致我的 ASP-程序集被加载(或映射)两次。在不同的程序集加载上下文中加载它意味着,加倍类型、静态变量等。在这方面,我注册的 IServerImpl
服务在控制器中搜索了另一种 IServerImpl
类型。类型名称相同,但不相同。
有关更多信息,请参阅技术挑战:https://docs.microsoft.com/en-us/dotnet/api/system.runtime.loader.assemblyloadcontext?view=net-5.0
关于 GitHub 的另一个问题:https://github.com/dotnet/runtime/issues/39783
在程序集解析事件中,我现在像这样返回加载的程序集,而不是再次加载它;
AppDomain.CurrentDomain.GetAssemblies()
.SingleOrDefault(asm => asm.FullName.StartsWith(args.Name.Split(',')[0] + ","))
仍然是 wellcome 的回答,阐明了“为什么我的 ASP-assembly 没有从框架中找到?”