public bool CanInfer(Type targetType) { if (targetType.IsClass) { return(RegisteredTypes.ContainsKey(targetType)); } return(RegisteredTypes.Values.ToArray().Exists(x => x.Inference != null && x.Inference.Equals(targetType))); }
public virtual object Resolve(Type abs) { abs = abs ?? throw new ArgumentNullException(nameof(abs)); if (!RegisteredTypes.ContainsKey(abs)) { throw new NotSupportedException( $"Тип {abs.FullName} не зарегистрирован в контейнере."); } if (Singletons.TryGetValue(abs, out var singleton) && singleton != null) { return(singleton); } if (ScopedInstances.TryGetValue(abs, out var scoped) && scoped != null) { return(scoped); } var imp = RegisteredTypes[abs]; var ctorInfo = imp.GetConstructors().Single(); var parameters = ctorInfo.GetParameters(); var args = parameters.Select(p => Resolve(p.ParameterType)).ToArray(); var instance = Activator.CreateInstance(imp, args); if (Singletons.ContainsKey(abs)) { Singletons[abs] = instance; } else if (ScopedInstances.ContainsKey(abs)) { ScopedInstances[abs] = instance; } return(instance); }
public virtual void RegisterTransient(Type abs, Type imp, bool rewrite = false) { abs = abs ?? throw new ArgumentNullException(nameof(abs)); imp = imp ?? throw new ArgumentNullException(nameof(imp)); if (!imp.IsClass) { throw new NotSupportedException( $"Тип {imp.FullName} не является классом."); } if (!rewrite && RegisteredTypes.ContainsKey(abs)) { throw new InvalidOperationException( $"Тип {abs.FullName} уже зарегистрирован в контейнере."); } if (!abs.IsAssignableFrom(imp)) { throw new InvalidOperationException( $"Тип {imp.FullName} не может быть приведён к типу {abs.FullName}."); } var foundTypes = new List <Type>(); if (!Singletons.ContainsKey(abs) && !ScopedInstances.ContainsKey(abs)) { foundTypes.Add(abs); } if (!Singletons.ContainsKey(imp) && !ScopedInstances.ContainsKey(imp) && !foundTypes.Contains(imp)) { foundTypes.Add(imp); } void CheckRecursion(Type type) { var ctors = type.GetConstructors(); if (ctors.Length != 1) { throw new NotSupportedException( $"Неразрешимая зависимость: контейнер не может выбрать вызываемый конструктор для типа {type.FullName}."); } var constructorInfo = ctors.Single(); var parameterTransientTypes = constructorInfo.GetParameters() .Select(p => p.ParameterType) .Except(Singletons.Keys) .Except(ScopedInstances.Keys) .Distinct() .ToArray(); foreach (var parameterType in parameterTransientTypes) { if (foundTypes.Contains(parameterType)) { throw new NotSupportedException( $"Неразрешимая зависимость: циклическая зависимость для типа {type.FullName} в типе параметра {parameterType.FullName}."); } if (parameterType.IsClass) { CheckRecursion(parameterType); } } foundTypes.AddRange(parameterTransientTypes); } CheckRecursion(imp); RegisteredTypes[abs] = imp; }