Skip to content

Commit

Permalink
Support for generic root arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
NikolayPianikov committed Nov 28, 2024
1 parent e2a6d57 commit 1f153c0
Show file tree
Hide file tree
Showing 15 changed files with 380 additions and 147 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ dotnet run
- [Generic async composition roots with constraints](readme/generic-async-composition-roots-with-constraints.md)
- [Custom generic argument](readme/custom-generic-argument.md)
- [Build up of an existing generic object](readme/build-up-of-an-existing-generic-object.md)
- [Generic root arguments](readme/generic-root-arguments.md)
### Attributes
- [Constructor ordinal attribute](readme/constructor-ordinal-attribute.md)
- [Member ordinal attribute](readme/member-ordinal-attribute.md)
Expand Down
71 changes: 46 additions & 25 deletions readme/complex-generics.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Defining generic type arguments using particular marker types like ```TT``` in t
```c#
interface IDependency<T>;

class Dependency<T> : IDependency<T>;
class Dependency<T>(T value) : IDependency<T>;

readonly record struct DependencyStruct<T> : IDependency<T>
where T : struct;
Expand Down Expand Up @@ -45,16 +45,19 @@ class Program<T>(IService<T, int, List<T>, Dictionary<T, int>> service)
DI.Setup(nameof(Composition))
// This hint indicates to not generate methods such as Resolve
.Hint(Hint.Resolve, "Off")
.RootArg<TT>("depArg")
.Bind<IDependency<TT>>().To<Dependency<TT>>()
.Bind<IDependency<TTS>>("value type").To<DependencyStruct<TTS>>()
.Bind<IDependency<TTS>>("value type")
.As(Lifetime.Singleton)
.To<DependencyStruct<TTS>>()
.Bind<IService<TT1, TTS2, TTList<TT1>, TTDictionary<TT1, TTS2>>>()
.To<Service<TT1, TTS2, TTList<TT1>, TTDictionary<TT1, TTS2>>>()
.To<Service<TT1, TTS2, TTList<TT1>, TTDictionary<TT1, TTS2>>>()

// Composition root
.Root<Program<string>>("Root");
.Root<Program<TT>>("GetRoot");

var composition = new Composition();
var program = composition.Root;
var program = composition.GetRoot<string>(depArg: "some value");
var service = program.Service;
service.ShouldBeOfType<Service<string, int, List<string>, Dictionary<string, int>>>();
service.Dependency1.ShouldBeOfType<Dependency<string>>();
Expand All @@ -69,25 +72,42 @@ The following partial class will be generated:
partial class Composition
{
private readonly Composition _root;
private readonly Lock _lock;

[OrdinalAttribute(20)]
private DependencyStruct<int> _singletonDependencyStruct49;
private bool _singletonDependencyStruct49Created;

[OrdinalAttribute(10)]
public Composition()
{
_root = this;
_lock = new Lock();
}

internal Composition(Composition parentScope)
{
_root = (parentScope ?? throw new ArgumentNullException(nameof(parentScope)))._root;
_lock = _root._lock;
}

public Program<string> Root
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Program<T1> GetRoot<T1>(T1 depArg)
where T1: notnull
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
if (!_root._singletonDependencyStruct49Created)
{
return new Program<string>(new Service<string, int, List<string>, Dictionary<string, int>>(new Dependency<string>(), new DependencyStruct<int>()));
using (_lock.EnterScope())
{
if (!_root._singletonDependencyStruct49Created)
{
_root._singletonDependencyStruct49 = new DependencyStruct<int>();
Thread.MemoryBarrier();
_root._singletonDependencyStruct49Created = true;
}
}
}

return new Program<T1>(new Service<T1, int, List<T1>, Dictionary<T1, int>>(new Dependency<T1>(depArg), _root._singletonDependencyStruct49));
}
}
```
Expand All @@ -98,32 +118,33 @@ Class diagram:
classDiagram
class Composition {
<<partial>>
+ProgramᐸStringᐳ Root
}
ServiceᐸStringˏInt32ˏListᐸStringᐳˏDictionaryᐸStringˏInt32ᐳᐳ --|> IServiceᐸStringˏInt32ˏListᐸStringᐳˏDictionaryᐸStringˏInt32ᐳᐳ
class ServiceᐸStringˏInt32ˏListᐸStringᐳˏDictionaryᐸStringˏInt32ᐳᐳ {
+Service(IDependencyᐸStringᐳ dependency1, IDependencyᐸInt32ᐳ dependency2)
+ProgramᐸT1ᐳ GetRootᐸT1ᐳ(T1 depArg)
}
DependencyᐸStringᐳ --|> IDependencyᐸStringᐳ
class DependencyᐸStringᐳ {
+Dependency()
ServiceᐸT1ˏInt32ˏListᐸT1ᐳˏDictionaryᐸT1ˏInt32ᐳᐳ --|> IServiceᐸT1ˏInt32ˏListᐸT1ᐳˏDictionaryᐸT1ˏInt32ᐳᐳ
class ServiceᐸT1ˏInt32ˏListᐸT1ᐳˏDictionaryᐸT1ˏInt32ᐳᐳ {
+Service(IDependencyᐸT1ᐳ dependency1, IDependencyᐸInt32ᐳ dependency2)
}
DependencyStructᐸInt32ᐳ --|> IDependencyᐸInt32ᐳ : "value type"
class DependencyStructᐸInt32ᐳ {
+DependencyStruct()
}
class IServiceᐸStringˏInt32ˏListᐸStringᐳˏDictionaryᐸStringˏInt32ᐳᐳ {
<<interface>>
DependencyᐸT1ᐳ --|> IDependencyᐸT1ᐳ
class DependencyᐸT1ᐳ {
+Dependency(T1 value)
}
class IDependencyᐸStringᐳ {
class IServiceᐸT1ˏInt32ˏListᐸT1ᐳˏDictionaryᐸT1ˏInt32ᐳᐳ {
<<interface>>
}
class IDependencyᐸInt32ᐳ {
<<interface>>
}
Composition ..> ProgramᐸStringᐳ : ProgramᐸStringᐳ Root
ProgramᐸStringᐳ *-- ServiceᐸStringˏInt32ˏListᐸStringᐳˏDictionaryᐸStringˏInt32ᐳᐳ : IServiceᐸStringˏInt32ˏListᐸStringᐳˏDictionaryᐸStringˏInt32ᐳᐳ
ServiceᐸStringˏInt32ˏListᐸStringᐳˏDictionaryᐸStringˏInt32ᐳᐳ *-- DependencyᐸStringᐳ : IDependencyᐸStringᐳ
ServiceᐸStringˏInt32ˏListᐸStringᐳˏDictionaryᐸStringˏInt32ᐳᐳ *-- DependencyStructᐸInt32ᐳ : "value type" IDependencyᐸInt32ᐳ
class IDependencyᐸT1ᐳ {
<<interface>>
}
Composition ..> ProgramᐸT1ᐳ : ProgramᐸT1ᐳ GetRootᐸT1ᐳ(T1 depArg)
ProgramᐸT1ᐳ *-- ServiceᐸT1ˏInt32ˏListᐸT1ᐳˏDictionaryᐸT1ˏInt32ᐳᐳ : IServiceᐸT1ˏInt32ˏListᐸT1ᐳˏDictionaryᐸT1ˏInt32ᐳᐳ
ServiceᐸT1ˏInt32ˏListᐸT1ᐳˏDictionaryᐸT1ˏInt32ᐳᐳ *-- DependencyᐸT1ᐳ : IDependencyᐸT1ᐳ
ServiceᐸT1ˏInt32ˏListᐸT1ᐳˏDictionaryᐸT1ˏInt32ᐳᐳ o-- "Singleton" DependencyStructᐸInt32ᐳ : "value type" IDependencyᐸInt32ᐳ
DependencyᐸT1ᐳ o-- T1 : Argument "depArg"
```

110 changes: 55 additions & 55 deletions readme/generic-async-composition-roots-with-constraints.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,60 +81,60 @@ partial class Composition
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Task<IService<T1, bool>> GetOtherServiceAsync<T1>(CancellationToken cancellationToken)
where T1: IDisposable
public Task<IService<T2, bool>> GetOtherServiceAsync<T2>(CancellationToken cancellationToken)
where T2: IDisposable
{
TaskFactory<IService<T1, bool>> perBlockTaskFactory2;
TaskFactory<IService<T2, bool>> perBlockTaskFactory2;
CancellationToken localCancellationToken61 = cancellationToken;
TaskCreationOptions transientTaskCreationOptions3 = TaskCreationOptions.None;
TaskCreationOptions localTaskCreationOptions62 = transientTaskCreationOptions3;
TaskContinuationOptions transientTaskContinuationOptions4 = TaskContinuationOptions.None;
TaskContinuationOptions localTaskContinuationOptions63 = transientTaskContinuationOptions4;
TaskScheduler transientTaskScheduler5 = TaskScheduler.Default;
TaskScheduler localTaskScheduler64 = transientTaskScheduler5;
perBlockTaskFactory2 = new TaskFactory<IService<T1, bool>>(localCancellationToken61, localTaskCreationOptions62, localTaskContinuationOptions63, localTaskScheduler64);
Func<IService<T1, bool>> perBlockFunc1 = new Func<IService<T1, bool>>([MethodImpl(MethodImplOptions.AggressiveInlining)] () =>
perBlockTaskFactory2 = new TaskFactory<IService<T2, bool>>(localCancellationToken61, localTaskCreationOptions62, localTaskContinuationOptions63, localTaskScheduler64);
Func<IService<T2, bool>> perBlockFunc1 = new Func<IService<T2, bool>>([MethodImpl(MethodImplOptions.AggressiveInlining)] () =>
{
OtherService<T1> transientOtherService6;
IDependency<T1> localDependency66 = new Dependency<T1>();
transientOtherService6 = new OtherService<T1>(localDependency66);
IService<T1, bool> localValue65 = transientOtherService6;
OtherService<T2> transientOtherService6;
IDependency<T2> localDependency66 = new Dependency<T2>();
transientOtherService6 = new OtherService<T2>(localDependency66);
IService<T2, bool> localValue65 = transientOtherService6;
return localValue65;
});
Task<IService<T1, bool>> transientTask0;
Task<IService<T2, bool>> transientTask0;
// Injects an instance factory
Func<IService<T1, bool>> localFactory67 = perBlockFunc1;
Func<IService<T2, bool>> localFactory67 = perBlockFunc1;
// Injects a task factory creating and scheduling task objects
TaskFactory<IService<T1, bool>> localTaskFactory68 = perBlockTaskFactory2;
TaskFactory<IService<T2, bool>> localTaskFactory68 = perBlockTaskFactory2;
// Creates and starts a task using the instance factory
transientTask0 = localTaskFactory68.StartNew(localFactory67);
return transientTask0;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Task<IService<T1, T>> GetMyRootAsync<T1, T>(CancellationToken cancellationToken)
where T1: IDisposable
public Task<IService<T2, T>> GetMyRootAsync<T2, T>(CancellationToken cancellationToken)
where T2: IDisposable
where T: struct
{
TaskFactory<IService<T1, T>> perBlockTaskFactory2;
TaskFactory<IService<T2, T>> perBlockTaskFactory2;
CancellationToken localCancellationToken69 = cancellationToken;
TaskCreationOptions transientTaskCreationOptions3 = TaskCreationOptions.None;
TaskCreationOptions localTaskCreationOptions70 = transientTaskCreationOptions3;
TaskContinuationOptions transientTaskContinuationOptions4 = TaskContinuationOptions.None;
TaskContinuationOptions localTaskContinuationOptions71 = transientTaskContinuationOptions4;
TaskScheduler transientTaskScheduler5 = TaskScheduler.Default;
TaskScheduler localTaskScheduler72 = transientTaskScheduler5;
perBlockTaskFactory2 = new TaskFactory<IService<T1, T>>(localCancellationToken69, localTaskCreationOptions70, localTaskContinuationOptions71, localTaskScheduler72);
Func<IService<T1, T>> perBlockFunc1 = new Func<IService<T1, T>>([MethodImpl(MethodImplOptions.AggressiveInlining)] () =>
perBlockTaskFactory2 = new TaskFactory<IService<T2, T>>(localCancellationToken69, localTaskCreationOptions70, localTaskContinuationOptions71, localTaskScheduler72);
Func<IService<T2, T>> perBlockFunc1 = new Func<IService<T2, T>>([MethodImpl(MethodImplOptions.AggressiveInlining)] () =>
{
IService<T1, T> localValue73 = new Service<T1, T>(new Dependency<T1>());
IService<T2, T> localValue73 = new Service<T2, T>(new Dependency<T2>());
return localValue73;
});
Task<IService<T1, T>> transientTask0;
Task<IService<T2, T>> transientTask0;
// Injects an instance factory
Func<IService<T1, T>> localFactory74 = perBlockFunc1;
Func<IService<T2, T>> localFactory74 = perBlockFunc1;
// Injects a task factory creating and scheduling task objects
TaskFactory<IService<T1, T>> localTaskFactory75 = perBlockTaskFactory2;
TaskFactory<IService<T2, T>> localTaskFactory75 = perBlockTaskFactory2;
// Creates and starts a task using the instance factory
transientTask0 = localTaskFactory75.StartNew(localFactory74);
return transientTask0;
Expand All @@ -148,53 +148,53 @@ Class diagram:
classDiagram
class Composition {
<<partial>>
+TaskᐸIServiceᐸT1ˏTᐳᐳ GetMyRootAsyncᐸT1ˏTᐳ(System.Threading.CancellationToken cancellationToken)
+TaskᐸIServiceᐸT1ˏBooleanᐳᐳ GetOtherServiceAsyncᐸT1ᐳ(System.Threading.CancellationToken cancellationToken)
+TaskᐸIServiceᐸT2ˏTᐳᐳ GetMyRootAsyncᐸT2ˏTᐳ(System.Threading.CancellationToken cancellationToken)
+TaskᐸIServiceᐸT2ˏBooleanᐳᐳ GetOtherServiceAsyncᐸT2ᐳ(System.Threading.CancellationToken cancellationToken)
}
class FuncᐸIServiceᐸT1ˏBooleanᐳᐳ
class TaskFactoryᐸIServiceᐸT1ˏBooleanᐳᐳ
class FuncᐸIServiceᐸT1ˏTᐳᐳ
class TaskFactoryᐸIServiceᐸT1ˏTᐳᐳ
OtherServiceᐸT1ᐳ --|> IServiceᐸT1ˏBooleanᐳ : "Other"
class OtherServiceᐸT1ᐳ
class FuncᐸIServiceᐸT2ˏBooleanᐳᐳ
class TaskFactoryᐸIServiceᐸT2ˏBooleanᐳᐳ
class FuncᐸIServiceᐸT2ˏTᐳᐳ
class TaskFactoryᐸIServiceᐸT2ˏTᐳᐳ
OtherServiceᐸT2ᐳ --|> IServiceᐸT2ˏBooleanᐳ : "Other"
class OtherServiceᐸT2ᐳ
class CancellationToken
class TaskCreationOptions
class TaskContinuationOptions
class TaskScheduler
ServiceᐸT1ˏTᐳ --|> IServiceᐸT1ˏTᐳ
class ServiceᐸT1ˏTᐳ {
+Service(IDependencyᐸT1ᐳ dependency)
ServiceᐸT2ˏTᐳ --|> IServiceᐸT2ˏTᐳ
class ServiceᐸT2ˏTᐳ {
+Service(IDependencyᐸT2ᐳ dependency)
}
DependencyᐸT1ᐳ --|> IDependencyᐸT1ᐳ
class DependencyᐸT1ᐳ {
DependencyᐸT2ᐳ --|> IDependencyᐸT2ᐳ
class DependencyᐸT2ᐳ {
+Dependency()
}
class IServiceᐸT1ˏBooleanᐳ {
class IServiceᐸT2ˏBooleanᐳ {
<<interface>>
}
class IServiceᐸT1ˏTᐳ {
class IServiceᐸT2ˏTᐳ {
<<interface>>
}
class IDependencyᐸT1ᐳ {
class IDependencyᐸT2ᐳ {
<<interface>>
}
Composition ..> TaskᐸIServiceᐸT1ˏBooleanᐳᐳ : TaskᐸIServiceᐸT1ˏBooleanᐳᐳ GetOtherServiceAsyncᐸT1ᐳ(System.Threading.CancellationToken cancellationToken)
Composition ..> TaskᐸIServiceᐸT1ˏTᐳᐳ : TaskᐸIServiceᐸT1ˏTᐳᐳ GetMyRootAsyncᐸT1ˏTᐳ(System.Threading.CancellationToken cancellationToken)
TaskᐸIServiceᐸT1ˏBooleanᐳᐳ o-- "PerBlock" FuncᐸIServiceᐸT1ˏBooleanᐳᐳ : "Other" FuncᐸIServiceᐸT1ˏBooleanᐳᐳ
TaskᐸIServiceᐸT1ˏBooleanᐳᐳ o-- "PerBlock" TaskFactoryᐸIServiceᐸT1ˏBooleanᐳᐳ : TaskFactoryᐸIServiceᐸT1ˏBooleanᐳᐳ
TaskᐸIServiceᐸT1ˏTᐳᐳ o-- "PerBlock" FuncᐸIServiceᐸT1ˏTᐳᐳ : FuncᐸIServiceᐸT1ˏTᐳᐳ
TaskᐸIServiceᐸT1ˏTᐳᐳ o-- "PerBlock" TaskFactoryᐸIServiceᐸT1ˏTᐳᐳ : TaskFactoryᐸIServiceᐸT1ˏTᐳᐳ
FuncᐸIServiceᐸT1ˏBooleanᐳᐳ *-- OtherServiceᐸT1ᐳ : "Other" IServiceᐸT1ˏBooleanᐳ
TaskFactoryᐸIServiceᐸT1ˏBooleanᐳᐳ o-- CancellationToken : Argument "cancellationToken"
TaskFactoryᐸIServiceᐸT1ˏBooleanᐳᐳ *-- TaskCreationOptions : TaskCreationOptions
TaskFactoryᐸIServiceᐸT1ˏBooleanᐳᐳ *-- TaskContinuationOptions : TaskContinuationOptions
TaskFactoryᐸIServiceᐸT1ˏBooleanᐳᐳ *-- TaskScheduler : TaskScheduler
FuncᐸIServiceᐸT1ˏTᐳᐳ *-- ServiceᐸT1ˏTᐳ : IServiceᐸT1ˏTᐳ
TaskFactoryᐸIServiceᐸT1ˏTᐳᐳ o-- CancellationToken : Argument "cancellationToken"
TaskFactoryᐸIServiceᐸT1ˏTᐳᐳ *-- TaskCreationOptions : TaskCreationOptions
TaskFactoryᐸIServiceᐸT1ˏTᐳᐳ *-- TaskContinuationOptions : TaskContinuationOptions
TaskFactoryᐸIServiceᐸT1ˏTᐳᐳ *-- TaskScheduler : TaskScheduler
OtherServiceᐸT1ᐳ *-- DependencyᐸT1ᐳ : IDependencyᐸT1ᐳ
ServiceᐸT1ˏTᐳ *-- DependencyᐸT1ᐳ : IDependencyᐸT1ᐳ
Composition ..> TaskᐸIServiceᐸT2ˏBooleanᐳᐳ : TaskᐸIServiceᐸT2ˏBooleanᐳᐳ GetOtherServiceAsyncᐸT2ᐳ(System.Threading.CancellationToken cancellationToken)
Composition ..> TaskᐸIServiceᐸT2ˏTᐳᐳ : TaskᐸIServiceᐸT2ˏTᐳᐳ GetMyRootAsyncᐸT2ˏTᐳ(System.Threading.CancellationToken cancellationToken)
TaskᐸIServiceᐸT2ˏBooleanᐳᐳ o-- "PerBlock" FuncᐸIServiceᐸT2ˏBooleanᐳᐳ : "Other" FuncᐸIServiceᐸT2ˏBooleanᐳᐳ
TaskᐸIServiceᐸT2ˏBooleanᐳᐳ o-- "PerBlock" TaskFactoryᐸIServiceᐸT2ˏBooleanᐳᐳ : TaskFactoryᐸIServiceᐸT2ˏBooleanᐳᐳ
TaskᐸIServiceᐸT2ˏTᐳᐳ o-- "PerBlock" FuncᐸIServiceᐸT2ˏTᐳᐳ : FuncᐸIServiceᐸT2ˏTᐳᐳ
TaskᐸIServiceᐸT2ˏTᐳᐳ o-- "PerBlock" TaskFactoryᐸIServiceᐸT2ˏTᐳᐳ : TaskFactoryᐸIServiceᐸT2ˏTᐳᐳ
FuncᐸIServiceᐸT2ˏBooleanᐳᐳ *-- OtherServiceᐸT2ᐳ : "Other" IServiceᐸT2ˏBooleanᐳ
TaskFactoryᐸIServiceᐸT2ˏBooleanᐳᐳ o-- CancellationToken : Argument "cancellationToken"
TaskFactoryᐸIServiceᐸT2ˏBooleanᐳᐳ *-- TaskCreationOptions : TaskCreationOptions
TaskFactoryᐸIServiceᐸT2ˏBooleanᐳᐳ *-- TaskContinuationOptions : TaskContinuationOptions
TaskFactoryᐸIServiceᐸT2ˏBooleanᐳᐳ *-- TaskScheduler : TaskScheduler
FuncᐸIServiceᐸT2ˏTᐳᐳ *-- ServiceᐸT2ˏTᐳ : IServiceᐸT2ˏTᐳ
TaskFactoryᐸIServiceᐸT2ˏTᐳᐳ o-- CancellationToken : Argument "cancellationToken"
TaskFactoryᐸIServiceᐸT2ˏTᐳᐳ *-- TaskCreationOptions : TaskCreationOptions
TaskFactoryᐸIServiceᐸT2ˏTᐳᐳ *-- TaskContinuationOptions : TaskContinuationOptions
TaskFactoryᐸIServiceᐸT2ˏTᐳᐳ *-- TaskScheduler : TaskScheduler
OtherServiceᐸT2ᐳ *-- DependencyᐸT2ᐳ : IDependencyᐸT2ᐳ
ServiceᐸT2ˏTᐳ *-- DependencyᐸT2ᐳ : IDependencyᐸT2ᐳ
```

48 changes: 24 additions & 24 deletions readme/generic-composition-roots-with-constraints.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,21 +79,21 @@ partial class Composition
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public IService<T1, bool> GetOtherService<T1>()
where T1: IDisposable
public IService<T2, bool> GetOtherService<T2>()
where T2: IDisposable
{
OtherService<T1> transientOtherService0;
IDependency<T1> localDependency76 = new Dependency<T1>();
transientOtherService0 = new OtherService<T1>(localDependency76);
OtherService<T2> transientOtherService0;
IDependency<T2> localDependency76 = new Dependency<T2>();
transientOtherService0 = new OtherService<T2>(localDependency76);
return transientOtherService0;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public IService<T1, T> GetMyRoot<T1, T>()
where T1: IDisposable
public IService<T2, T> GetMyRoot<T2, T>()
where T2: IDisposable
where T: struct
{
return new Service<T1, T>(new Dependency<T1>());
return new Service<T2, T>(new Dependency<T2>());
}
}
```
Expand All @@ -104,31 +104,31 @@ Class diagram:
classDiagram
class Composition {
<<partial>>
+IServiceᐸT1ˏTᐳ GetMyRootᐸT1ˏTᐳ()
+IServiceᐸT1ˏBooleanᐳ GetOtherServiceᐸT1ᐳ()
+IServiceᐸT2ˏTᐳ GetMyRootᐸT2ˏTᐳ()
+IServiceᐸT2ˏBooleanᐳ GetOtherServiceᐸT2ᐳ()
}
OtherServiceᐸT1ᐳ --|> IServiceᐸT1ˏBooleanᐳ : "Other"
class OtherServiceᐸT1ᐳ
ServiceᐸT1ˏTᐳ --|> IServiceᐸT1ˏTᐳ
class ServiceᐸT1ˏTᐳ {
+Service(IDependencyᐸT1ᐳ dependency)
OtherServiceᐸT2ᐳ --|> IServiceᐸT2ˏBooleanᐳ : "Other"
class OtherServiceᐸT2ᐳ
ServiceᐸT2ˏTᐳ --|> IServiceᐸT2ˏTᐳ
class ServiceᐸT2ˏTᐳ {
+Service(IDependencyᐸT2ᐳ dependency)
}
DependencyᐸT1ᐳ --|> IDependencyᐸT1ᐳ
class DependencyᐸT1ᐳ {
DependencyᐸT2ᐳ --|> IDependencyᐸT2ᐳ
class DependencyᐸT2ᐳ {
+Dependency()
}
class IServiceᐸT1ˏBooleanᐳ {
class IServiceᐸT2ˏBooleanᐳ {
<<interface>>
}
class IServiceᐸT1ˏTᐳ {
class IServiceᐸT2ˏTᐳ {
<<interface>>
}
class IDependencyᐸT1ᐳ {
class IDependencyᐸT2ᐳ {
<<interface>>
}
Composition ..> OtherServiceᐸT1ᐳ : IServiceᐸT1ˏBooleanᐳ GetOtherServiceᐸT1ᐳ()
Composition ..> ServiceᐸT1ˏTᐳ : IServiceᐸT1ˏTᐳ GetMyRootᐸT1ˏTᐳ()
OtherServiceᐸT1ᐳ *-- DependencyᐸT1ᐳ : IDependencyᐸT1ᐳ
ServiceᐸT1ˏTᐳ *-- DependencyᐸT1ᐳ : IDependencyᐸT1ᐳ
Composition ..> OtherServiceᐸT2ᐳ : IServiceᐸT2ˏBooleanᐳ GetOtherServiceᐸT2ᐳ()
Composition ..> ServiceᐸT2ˏTᐳ : IServiceᐸT2ˏTᐳ GetMyRootᐸT2ˏTᐳ()
OtherServiceᐸT2ᐳ *-- DependencyᐸT2ᐳ : IDependencyᐸT2ᐳ
ServiceᐸT2ˏTᐳ *-- DependencyᐸT2ᐳ : IDependencyᐸT2ᐳ
```

Loading

0 comments on commit 1f153c0

Please sign in to comment.