依赖注入 - 这是否违反了关注点分离?这是、关注点、违反了

2023-09-03 17:44:10 作者:王牌情敌i

是否依赖注入违反关注的分离,因为它涉及到一个n层架构?

Does Dependency Injection violate the Separation of Concerns as it pertains to an n-tier architecture?

假设你有以下项目:

MyApp.Data
MyApp.Business
MyApp.Web

如果我是用DI告诉业务层要使用的数据上下文,这是不是违反了SoC的?这意味着用户界面(MyApp.Web)会确保有足够的数据访问层(MyApp.Data)告诉业务层(MyApp.Business)要使用的背景知识,对吧?

If I were to use DI to tell the Business Layer which Data Context to use, wouldn't this violate SoC? This would mean the UI (MyApp.Web) would have to have knowledge of the Data Access Layer (MyApp.Data) to tell the Business Layer (MyApp.Business) which context to use, right?

public class WebForm {
    public void Save(Object dto) {
        BusinessObject bo = new BusinessObject(Data.MyDataContext);
        bo.ValidateAndSave(dto);
    }
}

我一直以为,在N层体系结构,每一层只能有下一层的了解(UI对企业,企业对数据)。这是不是一个真正的大问题?

I always thought, in an n-tier architecture, each tier should only have knowledge of the next tier (UI to Business, Business to Data). Is this not really a big deal?

推荐答案

没有,它不违反SoC的,实际上它鼓励它。

No, it does not violate the SoC, in fact it encourages it.

现在的问题是,在你的榜样,你不使用DI,至少在用户界面。你是让Web窗体明确构建,而不是让那些依赖注入它所需要的对象。

The problem is that in your example you are not using DI, at least in the UI. You are letting the WebForm explicitly build the objects it needs, instead of getting those dependencies injected.

主要的想法是有一个中央引导程序中的一个应用程序,创建了根对象,得到它依赖这又与其他依赖关系构建等。既然是这样一个痛苦的手工做的,你靠DI容器做自动使用约定或者通过配置,或者两者兼而有之。

The main idea is to have a central bootstrapper in an app that creates the root object, which gets it dependencies which in turn are constructed from other dependencies and so on. Given that is such a pain to do manually, you rely on DI containers that do that automatically using conventions or via configuration, or both.

所以,在你的榜样,你将有web窗体使用DI容器构成,你会指定的依赖,比方说,一个IBusinessObject这反过来将取决于在DataContext做的事情与这些实体和DTO的创建。然后在该保存方法应使用,通过使用一个从外部注入的实例,手动或通过一容器,但总是在应用生命周期的某些根点

So in your example, you would have the WebForm be constructed using a DI container and you would specify dependencies to, say, an IBusinessObject that would in turn depend on the DataContext to do things with those entities and create them from dto's. Then in that Save method you would use that by using the instance that was injected from outside, either manually or via a container, but always in some root point in the app lifecycle