ServiceStack IAppSettings 未就绪,如果在构造函数中使用,将导致 NULL 引用异常

ServiceStack IAppSettings was not ready and would result NULL reference exception if used in constructor

IAppSettings 构造函数中的 IoC 似乎尚未准备好实施。

在详细介绍之前,我已经阅读了类似的问题:

@mythz 都回答说他无法重现。

来自文档

“ServiceStack 使 AppSettings 成为第一个-class 属性,默认查看 .NET 的 App/Web.config。”:https://docs.servicestack.net/appsettings#first-class-appsettings

而Funq中有default IoC registration already当你要求IAppSettings时给你AppSettings:

我有什么

我所有的代码都在仓库中:https://github.com/davidliang2008/MvcWithServiceStack

演示应用程序只是一个 ASP.NET 使用模板构建的 MVC 应用程序 (.NET 4.8),安装了 ServiceStack (5.12.0):

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        ...
        new AppHost().Init();
    }
}

public class AppHost : AppHostBase
{
    public AppHost() : base("MvcWithServiceStack", typeof(ServiceBase).Assembly) { }

    public override void Configure(Container container)
    {
        SetConfig(new HostConfig
        {
            HandlerFactoryPath = "api";
        }

        ControllerBuilder.Current.SetControllerFactory(new FunqControllerFactory(container));
    }
}

然后我有一个 ServiceStack 服务的基础 class,还有一个 HelloService 只是为了演示:

public abstract class ServiceBase : Service { }

public class HelloService : ServiceBase
{
    public IAppSettings AppSettings { get; set; }

    public object Get(HelloRequest request)
    {
        return new HelloResponse
        {
            Result = $"Hello, { request.Name }! Your custom value is { AppSettings.Get<string>("custom") }."
        };
    }
}

[Route("/hello/{name}")]
public class HelloRequest : IReturn<HelloResponse>
{
    public string Name { get; set; }
}

public class HelloResponse
{
    public string Result { get; set; }
}

什么有效

当您不在构造函数中使用 IAppSettings 时,无论是在 HelloService 或其基础 class ServiceBase 中,一切正常。

当您将项目克隆到本地时,如果您导航到 /api/hello/{your-name},您将看到它的响应将能够从 web.config:

获取自定义值

什么不起作用

当您尝试获取 IAppSettings 并在构造函数中使用某些应用程序设置值初始化其他东西时 - 无论它是在子 class 还是基础 class 中, IAppSettings 将无法从 IoC 获取实现,并导致 NULL 引用异常:

public abstract class ServiceBase : Service
{
    public IAppSettings AppSettings { get; set; }

    public ServiceBase()
    {
        // AppSettings would be NULL
        var test = AppSettings.Get<string>("custom");
    }
}

public class HelloService : ServiceBase
{
    public HelloService()
    {
        // AppSettings would be NULL
        var test = AppSettings.Get<string>("custom");
    }
}

您不能在构造函数中使用任何 属性 依赖项,因为属性只能在创建 class 并且构造函数为 运行.

之后注入

您只能通过使用构造函数注入在构造函数中访问它,例如:

public class HelloService : ServiceBase
{
    public HelloService(IAppSettings appSettings)
    {
        var test = appSettings.Get<string>("custom");
    }
}

或者通过单例访问依赖:

public class HelloService : ServiceBase
{
    public HelloService()
    {
        var test = HostContext.AppSettings.Get<string>("custom");
    }
}