使用 IoC.Resolve 时可以有条件构造类吗?

发布于 2024-08-28 14:30:35 字数 577 浏览 6 评论 0原文

我有一个具有重载构造函数的服务类。一个构造函数有 5 个参数,另一个有 4 个参数。

在调用之前,

var service = IoC.Resolve<IService>();

我想做一个测试,并根据此测试的结果,使用特定的构造函数解析服务。换句话说,

        bool testPassed = CheckCertainConditions();
        if (testPassed)
        {
            //Resolve service using 5 paramater constructor
        }
        else
        {
            //Resolve service using 4 parameter constructor
            //If I use 5 parameter constructor under these conditions I will have epic fail.
        }

有没有一种方法可以指定我要使用哪一个?

I have a service class which has overloaded constructors. One constructor has 5 parameters and the other has 4.

Before I call,

var service = IoC.Resolve<IService>();

I want to do a test and based on the result of this test, resolve service using a specific constructor. In other words,

        bool testPassed = CheckCertainConditions();
        if (testPassed)
        {
            //Resolve service using 5 paramater constructor
        }
        else
        {
            //Resolve service using 4 parameter constructor
            //If I use 5 parameter constructor under these conditions I will have epic fail.
        }

Is there a way I can specify which one I want to use?

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

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

发布评论

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

评论(2

Oo萌小芽oO 2024-09-04 14:30:35

一般来说,当涉及到 DI 时,您应该注意构造函数中的歧义,因为您实际上是在对任何调用者说“我并不真正关心您是否使用其中之一” 。这不太可能是您想要的。

但是,一种与容器无关的解决方案是将条件实现包装到另一个实现相同接口的类:

public class ConditionalService : IService
{
    private readonly IService service;

    public ConditionalService()
    {
        bool testPassed = CheckCertainConditions();      
        if (testPassed)      
        {      
            // assign this.service using 5 paramater constructor      
        }      
        else      
        {      
            // assign this.service using 4 parameter constructor
        }  
    }

    // assuming that IService has a Foo method:
    public IBaz Foo(IBar bar)
    {
        return this.service.Foo(bar);
    }
}

如果您无法在构造函数中执行 CheckCertainConditions 检查,则可以使用惰性求值来代替。

让 ConditionalService 通过构造函数注入请求所有依赖项是一个好主意,但我将其排除在示例代码之外。

您可以向 DI 容器注册 ConditionalService,而不是真正的实现。

In general, you should watch out for ambiguity in constructors when it comes to DI because you are essentially saying to any caller that 'I don't really care if you use one or the other'. This is unlikely to be what you intended.

However, one container-agnostic solution is to wrap the conditional implementation into another class that implements the same interface:

public class ConditionalService : IService
{
    private readonly IService service;

    public ConditionalService()
    {
        bool testPassed = CheckCertainConditions();      
        if (testPassed)      
        {      
            // assign this.service using 5 paramater constructor      
        }      
        else      
        {      
            // assign this.service using 4 parameter constructor
        }  
    }

    // assuming that IService has a Foo method:
    public IBaz Foo(IBar bar)
    {
        return this.service.Foo(bar);
    }
}

If you can't perform the CheckCertainConditions check in the constructor, you can use lazy evaluation instead.

It would be a good idea to let ConditionalService request all dependencies via Constructor Injection, but I left that out of the example code.

You can register ConditionalService with the DI Container instead of the real implementation.

这个俗人 2024-09-04 14:30:35

我的根本问题是我试图解析具有以下签名的类:

public DatabaseSchemaSynchronisationService(IDatabaseService databaseService, IUserSessionManager userSessionManager)

这对我来说基本上没有用,因为我的 usersessionmanager 没有活动的 NHibernate.ISession 因为尚未建立与我的数据库的连接。我想做的是检查我是否有连接,然后才解析这个作为运行数据库更新脚本的服务的类。

当更改我的整个类以以不同的方式执行脚本时,我在其构造函数的签名中需要的只是:

public DatabaseSchemaSynchronisationService(ISessionFactory sessionFactory)

这允许我打开自己的会话。但我确实这样做了,但在尝试解析该类之前必须首先检查连接是否已准备好,但将 IDatabaseSchemaSynchronizationService 作为另一个类的构造函数的参数;这个类也在我无法检查数据库连接的地方得到解决,这是一个坏主意。

相反,在第二堂课中,我从构造函数签名中取出了 IDatabaseSchemaSynchronizationService 参数,并将其设为仅被实例化(解析)的局部变量:

if (connectionIsReady)

感谢所有回答的人。

My underlying problem was that I was trying to resolve my class which had the following signature:

public DatabaseSchemaSynchronisationService(IDatabaseService databaseService, IUserSessionManager userSessionManager)

This was basically useless to me because my usersessionmanager had no active NHibernate.ISession because a connection to my database had not yet been made. What I was trying to do was check if I did have a connection and only then resolve this class which served as a service to run database update scripts.

When changing my whole class to perform the scripts in a different way, all I needed in its constructor's signature was:

public DatabaseSchemaSynchronisationService(ISessionFactory sessionFactory)

This allowed me to open my own session. I did, however have to first check if the connection was ready before attempting to resolve the class, but having IDatabaseSchemaSynchronisationService as a parameter to another class's constructor; this class also gettting resolved somewhere where I could not check the db connection was a bad idea.

Instead in this second class, I took the IDatabaseSchemaSynchronisationService paramater out of the constructor signature and made it a local variable which only gets instantiated (resolved) :

if (connectionIsReady)

Thanks to everyone who answered.

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