Просмотр исходного кода

fix: parent container mutation

e22m4u 1 год назад
Родитель
Сommit
485f805579
3 измененных файлов с 85 добавлено и 37 удалено
  1. 21 0
      README.md
  2. 4 3
      src/service-container.js
  3. 60 34
      src/service-container.spec.js

+ 21 - 0
README.md

@@ -77,6 +77,27 @@ console.log(myDate2); // Wed Jan 01 2025 03:00:00
 console.log(myDate3); // Sun May 05 2030 03:00:00
 console.log(myDate3); // Sun May 05 2030 03:00:00
 ```
 ```
 
 
+### Наследование
+
+Конструктор `ServiceContainer` первым параметром принимает родительский
+контейнер, который используется как альтернативный, если конструктор
+запрашиваемого сервиса не зарегистрирован в текущем.
+
+```js
+class MyService {}
+
+// создание контейнера и регистрация
+// в нем сервиса MyService
+const parentContainer = new ServiceContainer();
+parentContainer.add(MyService);
+
+// использование предыдущего контейнера в качестве родителя,
+// и проверка доступности сервиса MyService
+const childContainer = new ServiceContainer(parentContainer);
+const hasService = childContainer.has(MyService);
+console.log(hasService); // true
+```
+
 ## Service
 ## Service
 
 
 Методы:
 Методы:

+ 4 - 3
src/service-container.js

@@ -53,10 +53,11 @@ export class ServiceContainer {
         ctor,
         ctor,
       );
       );
     // если конструктор отсутствует в текущем
     // если конструктор отсутствует в текущем
-    // контейнере, то пытаемся получить сервис
-    // из родительского контейнера
-    if (!this._services.has(ctor) && this._parent)
+    // контейнере, но имеется в родительском,
+    // то запрашиваем сервис именно из него
+    if (!this._services.has(ctor) && this._parent && this._parent.has(ctor)) {
       return this._parent.get(ctor);
       return this._parent.get(ctor);
+    }
     let service = this._services.get(ctor);
     let service = this._services.get(ctor);
     // если экземпляр сервиса не найден
     // если экземпляр сервиса не найден
     // или переданы аргументы, то создаем
     // или переданы аргументы, то создаем

+ 60 - 34
src/service-container.spec.js

@@ -167,23 +167,36 @@ describe('ServiceContainer', function () {
         expect(givenArgs).to.be.eql(['foo', 'bar']);
         expect(givenArgs).to.be.eql(['foo', 'bar']);
       });
       });
 
 
-      it('instantiates from the parent container', function () {
-        class MyService extends Service {}
-        const parent = new ServiceContainer();
-        parent.add(MyService);
-        const child = new ServiceContainer(parent);
-        const res = child.get(MyService);
-        expect(res).to.be.instanceof(MyService);
-      });
-
-      it('returns an instance from the parent container', function () {
-        class MyService extends Service {}
-        const parent = new ServiceContainer();
-        const service = new MyService();
-        parent.set(MyService, service);
-        const child = new ServiceContainer(parent);
-        const res = child.get(MyService);
-        expect(res).to.be.eq(service);
+      describe('in case of the parent container', function () {
+        it('instantiates in the parent container', function () {
+          class MyService extends Service {}
+          const parent = new ServiceContainer();
+          parent.add(MyService);
+          const child = new ServiceContainer(parent);
+          const res = child.get(MyService);
+          expect(res).to.be.instanceof(MyService);
+        });
+
+        it('returns an instance from the parent container', function () {
+          class MyService extends Service {}
+          const parent = new ServiceContainer();
+          const service = parent.get(MyService);
+          const child = new ServiceContainer(parent);
+          const res = child.get(MyService);
+          expect(res).to.be.eq(service);
+        });
+
+        it('does not adds the given constructor to the parent container', function () {
+          class MyService extends Service {}
+          const parent = new ServiceContainer();
+          const child = new ServiceContainer(parent);
+          const service = child.get(MyService);
+          expect(service).to.be.instanceof(MyService);
+          const res1 = child.has(MyService);
+          const res2 = parent.has(MyService);
+          expect(res1).to.be.true;
+          expect(res2).to.be.false;
+        });
       });
       });
     });
     });
 
 
@@ -281,23 +294,36 @@ describe('ServiceContainer', function () {
         expect(givenArgs).to.be.eql(['foo', 'bar']);
         expect(givenArgs).to.be.eql(['foo', 'bar']);
       });
       });
 
 
-      it('instantiates from the parent container', function () {
-        class MyService {}
-        const parent = new ServiceContainer();
-        parent.add(MyService);
-        const child = new ServiceContainer(parent);
-        const res = child.get(MyService);
-        expect(res).to.be.instanceof(MyService);
-      });
-
-      it('returns an instance from the parent container', function () {
-        class MyService {}
-        const parent = new ServiceContainer();
-        const service = new MyService();
-        parent.set(MyService, service);
-        const child = new ServiceContainer(parent);
-        const res = child.get(MyService);
-        expect(res).to.be.eq(service);
+      describe('in case of the parent container', function () {
+        it('instantiates in the parent container', function () {
+          class MyService {}
+          const parent = new ServiceContainer();
+          parent.add(MyService);
+          const child = new ServiceContainer(parent);
+          const res = child.get(MyService);
+          expect(res).to.be.instanceof(MyService);
+        });
+
+        it('returns an instance from the parent container', function () {
+          class MyService {}
+          const parent = new ServiceContainer();
+          const service = parent.get(MyService);
+          const child = new ServiceContainer(parent);
+          const res = child.get(MyService);
+          expect(res).to.be.eq(service);
+        });
+
+        it('does not adds the given constructor to the parent container', function () {
+          class MyService {}
+          const parent = new ServiceContainer();
+          const child = new ServiceContainer(parent);
+          const service = child.get(MyService);
+          expect(service).to.be.instanceof(MyService);
+          const res1 = child.has(MyService);
+          const res2 = parent.has(MyService);
+          expect(res1).to.be.true;
+          expect(res2).to.be.false;
+        });
       });
       });
     });
     });
   });
   });