servicestack - ServiceStack 消息 API:在 OnAfterInit 中使用 HostContet.AppHost.ExecuteMessage 会产生 NullReferenceException
问题描述
如前所述,我有时会使用这种方法在内部执行服务:
IMessage theMessage = new Message<Startup>(new Startup());
var reply = HostContext.AppHost.ExecuteMessage(theMessage); // The way to get the pipeline to execute when we do internal call, and get DI to work etc
这工作得很好并且符合预期,除了在一种情况下:当我从OnAfterInit
方法中调用它时,我会覆盖它。
这个想法是我想在 AppHost 准备好时做一些启动工作,在初始化之后,但是这样做时,它会失败并显示NullReferenceException
:
public override void OnAfterInit()
{
base.OnAfterInit();
IMessage theMessage = new Message<Startup>(new Startup());
var reply = HostContext.AppHost.ExecuteMessage(theMessage);
}
错误:
at ServiceStack.ServiceStackHost.<ApplyRequestConvertersAsync>d__361.MoveNext() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\ServiceStackHost.Runtime.cs:line 45
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at ServiceStack.Host.ServiceController.ExecuteMessage(IMessage dto, IRequest req) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\ServiceController.cs:line 584
at ServiceStack.ServiceStackHost.ExecuteMessage(IMessage mqMessage) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\ServiceStackHost.cs:line 1486
at Test.Test.OnAfterInit() in C:\Git\Test\Test.cs:line 59
似乎并非所有内容都已初始化并准备就绪。如果我这样做,它会起作用:
public override void OnAfterInit()
{
base.OnAfterInit();
System.Threading.Timer t = new System.Threading.Timer((o) =>
{
IMessage theMessage = new Message<Startup>(new Startup());
var reply = HostContext.AppHost.ExecuteMessage(theMessage);
}, null, 100, int.MaxValue);
}
我很高兴知道我是否遗漏了什么,以及是否有更好的方法来解决这个问题。定时器的东西有效,但它不适合我。
解决方案
理想情况下,执行服务应该在运行时而不是在启动时完成,但是如果您确实想要执行服务,您需要在启动的最后执行它们,此时 ServiceStack 的其余部分已经像在中一样初始化AfterInitCallbacks
,例如:
AfterInitCallbacks.Add(host =>
host.ExecuteMessage(new Message<Startup>(new Startup()));