public void AddInstance <TService>(TService instance) { var instanceDelivery = new InstanceDelivery(LifetimeStatus.Singleton, instance?.GetType()); // don't check the constructor singletons.AddOrUpdate(instanceDelivery, instance, (key, existing) => instance); Add(typeof(TService), instanceDelivery); }
private void Add(Type type, InstanceDelivery instanceDelivery) => types.AddOrUpdate(type, t => new[] { instanceDelivery }.ToImmutableList(), (t, l) => { var b = l.ToBuilder(); b.Add(instanceDelivery); return(b.ToImmutable()); });
private object Resolve(Stack <Type> creating, InstanceDelivery instanceDelivery) { switch (instanceDelivery.Lifetime) { case LifetimeStatus.Singleton: return(singletons.GetOrAdd(instanceDelivery, d => Create(creating, d))); case LifetimeStatus.Transient: return(Create(creating, instanceDelivery)); default: throw new ArgumentOutOfRangeException(); } }
private object Create(Stack <Type> creating, InstanceDelivery instanceDelivery) { if (creating.Contains(instanceDelivery.Type)) { var allTypes = new[] { instanceDelivery.Type }.Concat(creating).ToArray(); throw new ResolutionException("Circular reference when creating the following types:" + $"{Environment.NewLine}{string.Join(Environment.NewLine, allTypes.Select(t => t.FullName))}"); } creating.Push(instanceDelivery.Type); try { var constructor = constructors.GetOrAdd(instanceDelivery.Type, GetConstructor); //should always already be in. var parameterValues = new List <object>(); foreach (var parameterInfo in constructor.GetParameters()) { var parameterValue = Resolve(creating, parameterInfo.ParameterType); parameterValues.Add(parameterValue); } try { var resolution = constructor.Invoke(parameterValues.ToArray()); return(resolution); } catch (Exception e) { var allTypes = creating.ToArray(); //already got the type we're trying to create in the stack throw new ResolutionException("Resolution failed when creating the following types:" + $"{Environment.NewLine}{string.Join(Environment.NewLine, allTypes.Select(t => t.FullName))}", e); } } finally { creating.Pop(); } }