-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Niyaz Kashafutdinov
committed
Mar 7, 2024
1 parent
1f96123
commit bbddd22
Showing
123 changed files
with
1,533 additions
and
1,146 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace ReDI | ||
{ | ||
public class Container : IDisposable | ||
{ | ||
|
||
private readonly List<ServiceRegistration> _registrations = new List<ServiceRegistration>(); | ||
private readonly Dictionary<Type, HashSet<ServiceRegistration>> _registrationsByInterface = new Dictionary<Type, HashSet<ServiceRegistration>>(); | ||
|
||
private bool _isDisposed; | ||
private HashSet<Type> _constructingTypes = new HashSet<Type>(); | ||
|
||
internal Container(IEnumerable<BindingInfo> bindings) | ||
{ | ||
var toBuild = new HashSet<ServiceRegistration>(); | ||
|
||
foreach (var binding in bindings) | ||
{ | ||
var registration = new ServiceRegistration(binding.BoundType, binding.AlwaysNewInstance, binding.IsDisposable, binding.Instance); | ||
|
||
foreach (var interfaceType in binding.AssociatedInterfaces) | ||
{ | ||
if (!_registrationsByInterface.TryGetValue(interfaceType, out var existingRegistrations)) | ||
{ | ||
existingRegistrations = new HashSet<ServiceRegistration>(); | ||
_registrationsByInterface[interfaceType] = existingRegistrations; | ||
} | ||
|
||
existingRegistrations.Add(registration); | ||
} | ||
|
||
if (binding.CreateOnBuild) | ||
toBuild.Add(registration); | ||
|
||
_registrations.Add(registration); | ||
} | ||
|
||
foreach (var buildingService in toBuild) | ||
{ | ||
Build(buildingService); | ||
} | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
if (_isDisposed) | ||
{ | ||
#if DEBUG | ||
throw new ObjectDisposedException("Container is already disposed"); | ||
#endif | ||
return; | ||
} | ||
|
||
foreach (var registration in _registrations) | ||
{ | ||
if (registration.IsDisposable && registration.Instance is IDisposable disposable) | ||
disposable.Dispose(); | ||
} | ||
|
||
_isDisposed = true; | ||
} | ||
|
||
public T? Resolve<T>() where T : class | ||
{ | ||
var obj = Resolve(typeof(T)); | ||
return obj != null ? (T)obj : null; | ||
} | ||
|
||
public object? Resolve(Type type) | ||
{ | ||
CheckIfDisposed(); | ||
|
||
if (IsGenericList(type)) | ||
{ | ||
return ResolveList(type); | ||
} | ||
else | ||
{ | ||
return ResolveSingle(type); | ||
} | ||
} | ||
|
||
private object? ResolveSingle(Type type) | ||
{ | ||
if (!_registrationsByInterface.TryGetValue(type, out var registrations)) | ||
{ | ||
return null; | ||
} | ||
|
||
return Build(registrations.First()); | ||
} | ||
|
||
private object? ResolveList(Type type) | ||
{ | ||
var serviceType = GetListTypeArgument(type); | ||
|
||
if (!_registrationsByInterface.TryGetValue(serviceType, out var registrations)) | ||
{ | ||
return null; | ||
} | ||
|
||
var listType = typeof(List<>); | ||
var constructedListType = listType.MakeGenericType(serviceType); | ||
|
||
var instance = Activator.CreateInstance(constructedListType, registrations.Count) as IList; | ||
foreach (var registration in registrations) | ||
{ | ||
instance.Add(Build(registration)); | ||
} | ||
|
||
return instance; | ||
} | ||
|
||
private bool IsGenericList(Type type) | ||
{ | ||
return type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(List<>)); | ||
} | ||
|
||
private Type GetListTypeArgument(Type type) | ||
{ | ||
return type.GetGenericArguments()[0]; | ||
} | ||
|
||
private void CheckIfDisposed() | ||
{ | ||
#if DEBUG | ||
if (_isDisposed) | ||
throw new ObjectDisposedException("Container is disposed"); | ||
#endif | ||
} | ||
|
||
private object Build(ServiceRegistration registration) | ||
{ | ||
if (registration.AlwaysNewInstance || registration.Instance == null) | ||
{ | ||
CheckForCircularDependency(registration); | ||
registration.Instance = registration.Create(this); | ||
_constructingTypes.Remove(registration.ServiceType); | ||
} | ||
|
||
if (!registration.IsInjected) | ||
{ | ||
registration.Inject(registration.Instance, this); | ||
} | ||
|
||
return registration.Instance; | ||
} | ||
|
||
private void CheckForCircularDependency(ServiceRegistration registration) | ||
{ | ||
if (!_constructingTypes.Add(registration.ServiceType)) | ||
{ | ||
throw new CircularDependencyFoundException(registration.ServiceType); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
namespace Remouse.DI | ||
namespace ReDI | ||
{ | ||
public class ContainerBuilder | ||
{ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System; | ||
|
||
namespace ReDI | ||
{ | ||
public class CircularDependencyFoundException : Exception | ||
{ | ||
private readonly Type _type; | ||
|
||
public CircularDependencyFoundException(Type type) { _type = type; } | ||
|
||
public override string Message { get => $"{_type} refers to circular dependency"; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using System; | ||
|
||
namespace ReDI | ||
{ | ||
public class InjectingServiceNotRegisteredException : Exception | ||
{ | ||
private readonly Type _serviceType; | ||
private readonly Type _injectingType; | ||
|
||
public InjectingServiceNotRegisteredException(Type serviceType, Type injectingType) | ||
{ | ||
_serviceType = serviceType; | ||
_injectingType = injectingType; | ||
} | ||
|
||
public override string Message { get => $"Not found service of type {_injectingType}, required for service {_serviceType}"; } | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
ReDI/Exceptions/ModuleInstanceAlreadyRegisteredException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using System; | ||
|
||
namespace ReDI | ||
{ | ||
public class ModuleInstanceAlreadyRegisteredException : Exception | ||
{ | ||
private readonly Module _module; | ||
|
||
public ModuleInstanceAlreadyRegisteredException(Module module) | ||
{ | ||
_module = module; | ||
} | ||
|
||
public override string Message { get => $"Instance of module {_module.GetType()} already registered"; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using System; | ||
|
||
namespace ReDI | ||
{ | ||
public class ModuleNotAssignedException : Exception | ||
{ | ||
private readonly Type _moduleType; | ||
|
||
public ModuleNotAssignedException(Type moduleType) | ||
{ | ||
_moduleType = moduleType; | ||
} | ||
|
||
public override string Message { get => $"Not find module instance of {_moduleType}, probably null registration"; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System; | ||
|
||
namespace ReDI | ||
{ | ||
public class NotFoundInjectingConstructorException : Exception | ||
{ | ||
private readonly Type _type; | ||
|
||
public NotFoundInjectingConstructorException(Type type) { _type = type; } | ||
|
||
public override string Message { get => $"Not found constructor with [Inject] attribute, multiple constructor's defined in {_type}"; } | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
ReDI/Exceptions/SecondCallBuildServiceInternalException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System; | ||
|
||
namespace ReDI | ||
{ | ||
public class SecondCallBuildServiceInternalException : Exception | ||
{ | ||
private readonly Type _type; | ||
|
||
public SecondCallBuildServiceInternalException(Type type) { _type = type; } | ||
|
||
public override string Message { get => $"Build of serivce {_type} was called second time"; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System; | ||
|
||
namespace ReDI | ||
{ | ||
public class TooManyInjectingConstructorsException: Exception | ||
{ | ||
private readonly Type _type; | ||
|
||
public TooManyInjectingConstructorsException(Type type) { _type = type; } | ||
|
||
public override string Message { get => $"{_type} contain more than 1 constructor with injecting attributes"; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using System; | ||
|
||
namespace ReDI | ||
{ | ||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Constructor | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] | ||
public class InjectAttribute : Attribute | ||
{ | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
namespace Remouse.DI | ||
namespace ReDI | ||
{ | ||
public abstract class Module | ||
{ | ||
|
Oops, something went wrong.