注入依赖项并将其成员之一设置为"this"是代码味道吗?

Mik*_*ike 10 c# testing dependency-injection

注入依赖项并将其中一个属性设置为当前实例是否是代码气味?我以这种方式设置代码,因此我可以完全隔离服务实现.我有一系列测试全部通过(包括StreamingSubscriber在逻辑类中设置实例).

例如

public class StreamingSubscriber
{
    private readonly ILogic _logic;

    public StreamingSubscriber(ILogic logic)
    {            
        _logic = logic;

        // Not sure I like this...
        _logic.StreamingSubscriber = this;
    }

    public void OnNotificationEvent(object sender, NotificationEventArgs args)
    {
        // Do something with _logic
        var email = _logic.FetchEmail(args);
        // consume the email (omitted for brevity)
    }
}

public class ExchangeLogic : ILogic
{   
    public StreamingSubscriber StreamingSubscriber { get; set; }

    public void Subscribe()
    {
        // Here is where I use StreamingSubscriber
        streamingConnection.OnNotificationEvent += StreamingSubscriber.OnNotificationEvent;
    }

    public IEmail FetchEmail(NotificationEventArgs notificationEventArgs)
    {
        // Fetch email from Exchange
    }
}
Run Code Online (Sandbox Code Playgroud)

如果这是一个代码味道你怎么去修复它?

编辑

我选择了这个实现的原因是因为我想成为能够测试时,streamingConnectionExchangeLogic被称为,这将消费者的电子邮件.目前的设计虽然不完美,但我可以编写类似这样的测试.

    [Test]
    public void FiringOnNotificationEvent_WillConsumeEmail()
    {
        // Arrange
        var subscriber = new StreamingSubscriber(ConsumerMock.Object, ExchangeLogicMock.Object);

        // Act
        subscriber.OnNotificationEvent(It.IsAny<object>(), It.IsAny<NotificationEventArgs>());

        // Assert
        ConsumerMock.Verify(x => x.Consume(It.IsAny<IEmail>()), Times.Once());
    }
Run Code Online (Sandbox Code Playgroud)

现在,如果没有进行全面的集成测试,这显然是不可能的.如果我告诉我ExchangeLogic要使用电子邮件.

Phi*_*ler 4

我觉得它本身并不是一种代码味道,不是。

然而,通过 setter 进行这项工作会产生一种情况,您可能会遇到计时问题 - 如果有人调用 subscribe 而 StreamingSubscriber 尚未设置怎么办?现在您必须编写代码来防范这种情况。我会避免使用设置器并重新排列它,这样您就可以调用“_logic.Subscribe(this)”。