C#中依赖注入消费的实例引用及执行顺序疑问
C#中依赖注入消费的实例引用及执行顺序疑问
嘿,这个问题问得挺细致的,我来给你掰扯清楚~
首先你完全不用担心会搞混两个g1,因为它们指向的是同一个Garage实例,根本不存在“二选一”的情况。咱们一步步拆解执行顺序和引用关系:
1. DI容器创建实例的流程
当你的代码需要用到Car实例时(比如通过DI注入或者直接从容器解析),容器会按以下步骤走:
- 先看
Garage的注册是Scoped,所以会在当前作用域(比如ASP.NET Core里的单个HTTP请求)内查找有没有已存在的Garage实例。如果没有,就新建一个;如果有,直接复用这个实例。 - 把拿到的这个
Garage实例,作为参数传给Car的构造函数(也就是你写的public class Car(Garage g1)里的g1参数)。
2. 构造函数里的赋值逻辑
你在构造函数里写的private readonly Garage g1 = g1;,其实是把构造函数参数里的Garage实例引用,赋值给了类的私有只读字段g1。这时候,参数g1和字段g1指向的是内存里同一个对象——打个比方,就像两个人拿着同一把钥匙,都能打开同一扇门。
如果不信的话,你可以在构造函数里加两行代码验证:
public class Car(Garage g1) { private readonly Garage g1 = g1; public Car() { Console.WriteLine($"参数g1的HashCode: {g1.GetHashCode()}"); Console.WriteLine($"字段g1的HashCode: {this.g1.GetHashCode()}"); } // ... 其他代码 }
运行后你会发现两个HashCode完全一样,这就实锤了它们是同一个实例。
3. 方法调用时的引用
当你调用ModifyCarAndStoreInGarage方法时,里面的g1.AddCar(car),用的就是你私有字段里的g1——而这个字段的引用,就是当初DI容器注入进来的那个Garage实例。所以整个过程里,自始至终都是同一个Garage对象在干活。
补充:Scoped的作用范围
因为你注册Garage用的是AddScoped,所以在同一个作用域内(比如同一个HTTP请求),不管是注入到Car里,还是注入到其他类里,拿到的都是同一个Garage实例。只有当作用域结束(比如请求处理完),这个实例才会被释放。
总结一下:不存在“方法不知道引用哪个g1”的问题,所有的g1都是同一个实例的引用,执行顺序就是DI先解析依赖注入构造函数,构造函数把引用存到字段,方法调用时直接用这个字段的引用就行~
内容来源于stack exchange
相关产品推荐
相关产品推荐

