【问题标题】:ServiceStack's Funq.Container not Newing-Up PropertiesServiceStack 的 Funq.Container 没有更新属性
【发布时间】:2014-02-16 18:46:08
【问题描述】:

我的服务使用一个实用程序类,该实用程序类有几个公共属性。我需要调用什么特别的东西来确保设置这些公共属性吗?

该服务使用 ASP.NET 主机。在 Global.ASAX 内部,我声明了一个新的 AppHostBase:

public class MyServiceHost : AppHostBase
{
    public MyServiceHost() : base("My Service Host", typeof(ServiceLibrary).Assembly) {}

    public override void Configure(Funq.Container container)
    {
        container.Register<IDbConnectionFactory>(dbConFactory);

        container.RegisterAutoWired<UtilityLibrary>();
        container.RegisterAutoWired<RepositoryLibrary>();
    }
}

在我的存储库库和实用程序库中都有一个主类。这可能类接收容器并注册更具体的实用程序和存储库:

public class UtilityLibrary
{
    public UtilityLibrary(Funq.Container container)
    {
        container.RegisterAutoWired<WidgetAActions>();
        container.RegisterAutoWired<WidgetBActions>();
    }
}

在下面的示例中,WidgetARepository 是在 RepositoryLibrary 类的构造函数中设置的。包含 WidgetARepository 的 RepositoryLibrary 类在 AppHost 的 Configure 方法中提供给 Container(上面的第一个 sn-p)。即便如此,WidgetARepository(如下)从未设置:

public class WidgetAActions
{
    public WidgetARepository WidgetARepository { get; set; }

    public WidgetA Get(string id)
    {
        var item = this.WidgetARepository.Get(id);
        if (item == null) { return null; }

        // Do something else

        return item;
    }
}

我必须手动拨打Resolve()吗?这样做似乎会破坏注入的目的。

【问题讨论】:

    标签: servicestack funq


    【解决方案1】:

    如果您想在 ServiceStack 服务之外使用 Funq Container Autowire IoC,那么您需要自己调用 Container.AutoWire 以让容器注入相关的依赖项。 此调用是在 ServiceStack 请求管道的幕后进行的。

    对于 ServiceStack v4:

    HostContext.Container.AutoWire(objectToPopulate);
    

    对于 ServiceStack v3:

    AppHostBase.Instance.Container.AutoWire(objectToPopulate);
    

    我通常会将此调用添加到我想要填充注入的对象的构造函数方法中。所以在你的情况下:

    public class WidgetAActions
    {
        public WidgetARepository WidgetARepository { get; set; }
    
        public WidgetAActions()
        {
            // (Substitute with v3 usage if required.)
            HostContext.Container.AutoWire(this);
        }
    
        ...
    }
    

    希望这会有所帮助。


    编辑:您是否考虑过让容器将相应的存储库注入WidgetAActions 的构造函数?

    container.RegisterAutoWired<WidgetAActions>(c => new WidgetAActions(c.Resolve<WidgetARepository>()));
    
    public class WidgetAActions
    {
        public WidgetARepository WidgetARepository { get; private set; }
    
        public WidgetAActions(WidgetARepository repository)
        {
            WidgetARepository = repository;
        }
    
        ...
    }
    

    编辑:或者您可以解析并将对象的公共属性设置为存储库,然后您不必有构造函数:

    container.RegisterAutoWired<WidgetAActions>(c => 
        new WidgetAActions { WidgetARepository = c.Resolve<WidgetARepository>() }
    );
    
    public class WidgetAActions
    {
        public WidgetARepository WidgetARepository { get; set; }
    
        ...
    }
    

    或者你可以在解析WidgetAActions时调用autowire:

    container.RegisterAutoWired<WidgetAActions>(c => {
        var actions = new WidgetAActions();
        container.AutoWire(actions); // All dependencies injected
        return actions;
    });
    
    public class WidgetAActions
    {
        public WidgetARepository WidgetARepository { get; set; }
    
        ...
    }
    

    【讨论】:

    • 从技术上讲,这些仍在服务范围内。 UtilityLibrary 类引用 RepositoryLibrary 类。两者都在服务的 AppHost 中向容器注册。唯一可能有点不寻常的因素(不明白为什么会这样)是 UtilityLibrary 和 RepositoryLibrary 都有将它们的子类添加到容器的构造函数。在这个场景中,WidgetARepository 将是 RepositoryLibrary 的子类。
    • @RyanD'Baisse 我可以看到您肯定将UtilityLibraryRepositoryLibraryWidgetAActionsWidgetBActions 添加到容器中,但Container.AutoWire 不会递归运行.因此,当 ServiceStack 服务运行时,它将自动连接您的 WidgetAActions,因为您已将其包含在您的服务中。但它看不到WidgetAActions 中的依赖关系。你必须按照我的建议拨打AutoWire。如果只有一个依赖项,则使用HostContext.Container.Resolve&lt;T&gt;()
    • @RyanD'Baisse 我添加了一种替代方法,当容器解析WidgetAActions 时,将存储库传递给WidgetAActions 的构造函数。
    • 很好的答案@Scott!只用过其中一个!
    • @Stephen Nice 很高兴它有用。
    猜你喜欢
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-26
    • 1970-01-01
    • 2021-10-21
    • 2018-05-12
    • 2015-07-22
    相关资源
    最近更新 更多