IoC / 依赖注入 - 如何处理上下文依赖(使用 Structuremap)

发布于 2024-11-24 18:15:30 字数 1263 浏览 1 评论 0原文

在我的应用程序中引入消息传递后,我似乎发现了一些异味。

在我的多租户应用程序中,文件系统针对每个租户进行抽象和限定范围。因此,如果服务需要创建文件,那么我们会注入一个 IFileSystem 实例,该实例的作用域将是租户目录/容器。

这是通过配置结构图来通过获取具有当前用户站点的上下文对象来构造 IFileSystem 实现来实现的。

现在我们需要在没有上下文且没有当前用户(在后台线程上)时使用文件系统。这是一个简单的示例:

    public class SiteContext
    {
        public string SiteId { get { return "Site123"; } }
    }

    public class FileSystemSettings
    {
        public string BaseDirectory { get; set; }
    }

    public interface IFileSystem { }

    public class DefaultFileSystem : IFileSystem
    {
        public DefaultFileSystem(FileSystemSettings settings)
        {

        }
    }

    public interface ISomeService { }

    public class SomeService : ISomeService
    {
        public SomeService(IFileSystem fileSystem)
        {

        }
    }

    public class TestMessageHandler : IMessageHandler<TestMessage>
    {
        public TestMessageHandler(ISomeService someService)
        {
            // oO we don't have access to site context here :(
        }
    }

我想我可以更改 FileSystem 实现以将 FileSystemSettings 公开为属性,以便之后可以对其进行设置。

然而,即使这样做仍然需要我手动构造 ISomeService 对象,这很痛苦,因为我的一些服务有许多依赖项 = 大量调用 ObjectFactory.GetInstance...

有想法吗?

After introducing messaging in my application it seems I've found a bit of a smell.

In my multi tenant application, the file system is abstracted and scoped for each tenant. So if a service needs to create files, then we inject an instance of IFileSystem which will be scoped to the tenants directory/container.

This is achieved by configuring structuremap to construct the IFileSystem implementation by getting of a contextual object that has the current users site.

Now we need to use the filesystem when there is no context and no current user (on a background thread). Here's a simple example:

    public class SiteContext
    {
        public string SiteId { get { return "Site123"; } }
    }

    public class FileSystemSettings
    {
        public string BaseDirectory { get; set; }
    }

    public interface IFileSystem { }

    public class DefaultFileSystem : IFileSystem
    {
        public DefaultFileSystem(FileSystemSettings settings)
        {

        }
    }

    public interface ISomeService { }

    public class SomeService : ISomeService
    {
        public SomeService(IFileSystem fileSystem)
        {

        }
    }

    public class TestMessageHandler : IMessageHandler<TestMessage>
    {
        public TestMessageHandler(ISomeService someService)
        {
            // oO we don't have access to site context here :(
        }
    }

I suppose I could change my FileSystem implementation to expose the FileSystemSettings as a property so it can be set afterwards.

However, even doing this would still require me to construct my ISomeService object manually, which is a pain as some of my services have a number of dependencies = lots of calls to ObjectFactory.GetInstance...

Ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梨涡 2024-12-01 18:15:30

您可以使用嵌套容器 并配置嵌套容器以具有上下文的虚拟实现。

代码大致如下:

using (var container = ObjectFactory.Container.GetNestedContainer())
{
    container.Configure(config => {
        config.For<ISiteContext>().Use<DummyContext>();
    });

    return container.GetInstance<TestMessageHandler>();
}

这应该设置 ISiteContext 的自定义(虚拟)实现,而不覆盖全局容器 (ObjectFactory.Container)。当然,如果没有更多信息,我无法为您提供 DummyContext 的适当实现。但这应该让你开始。

You could use nested containers and configure the nested container to have a dummy implementation of your context.

The code would approximately be:

using (var container = ObjectFactory.Container.GetNestedContainer())
{
    container.Configure(config => {
        config.For<ISiteContext>().Use<DummyContext>();
    });

    return container.GetInstance<TestMessageHandler>();
}

This should set a custom (dummy) implementation of ISiteContext without overwriting the global container (ObjectFactory.Container). Of course, I can't give you an appropriate implementation of DummyContext without more information. But this should get you started.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文