问题摘自this的github问题,并且与使用另一个程序集中的WebHost
构建Startup
有关。
在通过.Build()
配置的IWebHostBuilder
上调用WebHostBuilderExtensions.UseStartup(this IWebHostBuilder hostBuilder, Type startupType)
时,其中startupType
是通过其字符串从单独的.exe
程序集中检索的System.InvalidOperationException: 'Unable to resolve service for type 'Microsoft.Extensions.Configuration.IConfiguration' while attempting to activate 'WebAppWithAfterBuildTarget.Startup'.'
,在依赖注入时失败时间。
对于默认的ASP.NET Core + .NET Framework项目,将引发以下情况:
Microsoft.Build.[Framework/Utilities.v4.0]
最小复制步骤:
创建一个面向net462的名为“ MsBuildTask”的简单库项目。
添加对Microsoft.AspNetCore
程序集的引用,以及对.Http.Abstractions
+ public class RunStartup : Microsoft.Build.Utilities.Task
{
public string AssemblyToLoad { get; set; }
public override bool Execute()
{
var startupAssembly = Assembly.LoadFrom(Path.Combine(Directory.GetCurrentDirectory(), AssemblyToLoad));
var builder = WebHost.CreateDefaultBuilder();
builder.UseStartup(startupAssembly.FullName);
var host = builder.Build();
// ... do more stuff
return true;
}
}
nuget的引用。
像这样创建一个类:
<UsingTask AssemblyFile="..\MsBuildTask\bin\Debug\net462\MsBuildTask.dll" TaskName="RunStartup" />
<Target Name="RunStartup" AfterTargets="AfterBuild">
<RunStartup AssemblyToLoad="$(OutputPath)$(AssemblyName).exe" />
</Target>
构建MsBuildTask项目,将路径复制到dll输出(用于下面)。
在Visual Studio中创建一个ASP.NET Core 2.0 + .Net Framework 462项目。
在webapp csproj文件中,添加
AfterBuild
构建Web应用程序。 (出于调试目的,您可以在MsBuildTask> Properties> Debug中将Launch设置为可执行文件,将Executable设置为msbuild的路径,将Application参数设置为Webapp的路径,然后在MsBuildTask上按F5键)。 预期结果 构建任务将成功完成,我们可以与主机做更多有趣的事情。
实际结果
请注意,在MsBuildTask.RunStartup.Execute
目标部分中,运行.Build()
方法。
由于尚未注册IConfiguration
,因此在AspNetCore.Mvc
阶段失败。
更多技术细节
我尝试将启动程序复制到该项目(根据需要添加.UseStartup<Startup>()
nuget)并像在普通的ASP.NET Core应用程序中那样运行CreateDefaultBuilder()
,此操作成功。正是在按名称引用程序集时,我遇到了似乎未注册依赖项的错误。
在此方面有更多进展:
在我的asp.net核心项目中,我公开了一个Build()
方法,该方法调用与上述相同的方法,但是使用正确的类型上下文。然后,我通过反射对返回的对象调用Execute()
。这表明某些依赖项版本不匹配。我通过在 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(OnResolve);
方法的开头添加以下内容来解决这些问题:
private Assembly OnResolve(object sender, ResolveEventArgs args)
{
String currentFolder = Path.Combine(Directory.GetCurrentDirectory(), AssemblyToLoad);
AssemblyName requestedName = new AssemblyName(args.Name);
var resolvedAssembly = Assembly.LoadFrom(Path.Combine(currentFolder, requestedName.Name + (requestedName.Name == this.AssemblyName ? ".exe" : ".dll")));
if (resolvedAssembly.GetName().Version < requestedName.Version)
{
return null;
}
return resolvedAssembly;
}
具有这样定义的OnResolve,本质上是迫使dll从我的asp.net核心项目的bin目录中加载
System.Reflection.TargetInvocationException
HResult=0x80131604
Message=Exception has been thrown by the target of an invocation.
Source=mscorlib
StackTrace:
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at Swashbuckle.AspNetCore.MSBuild.SwaggerGenerator.Execute() in C:\dev\Swashbuckle.AspNetCore\src\Swashbuckle.AspNetCore.MSBuild\SwaggerGenerator.cs:line 42
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()
Inner Exception 1:
MissingMethodException: Method not found: 'Newtonsoft.Json.JsonSerializerSettings Microsoft.AspNetCore.Mvc.MvcJsonOptions.get_SerializerSettings()'.
但是由于某些原因,它似乎由于以下异常而失败:
SELECT `id`, `market_id`, `sector_id`, `symbol`, `name_en`, `name_ar`, `price`, `per`, `num_followers`, `num_posts`, `company_id`, `msgTrend`, `date`
From
(
SELECT `ticker_id`, `date`, COUNT(*) AS `msgTrend`
FROM `post_ticker` AS `mt`
INNER JOIN `post` AS `p` ON `post_id` = `p`.`id`
WHERE `ticker_id` IN (SELECT `id` FROM `ticker` WHERE `sector_id`!=0 AND `market_id`!=0)
AND `date`>=DATE_SUB((SELECT `date` FROM `post_ticker` INNER JOIN `post` AS `p` ON `post_id` = `p`.`id` ORDER BY `date` DESC LIMIT 1), INTERVAL 1 day)
GROUP BY `ticker_id`
) AS `mentioned_ticker`
INNER JOIN `ticker` on `ticker_id`=`id`
ORDER BY `msgTrend` DESC, `date` DESC
Limit 4