public Factory Register(Factory factory, Type serviceType, object serviceKey) { var implementationType = factory.ThrowIfNull().ImplementationType; if (implementationType != null && serviceType.ThrowIfNull() != typeof(object)) { Throw.If(!implementationType.GetImplementedTypes().Contains(serviceType), Error.EXPECTED_IMPL_TYPE_ASSIGNABLE_TO_SERVICE_TYPE, implementationType, serviceType); } lock (_syncRoot) { if (factory.Setup.Type == FactoryType.Decorator) { _decorators = _decorators.AddOrUpdate(serviceType, new[] { new DecoratorsEntry(factory) }, Sugar.Append); return factory; } var entry = _factories.GetOrAdd(serviceType, _ => new FactoriesEntry()); if (serviceKey == null) { // default factories will contain all the factories and LastDefault will just point to the latest, // for memory saving reasons. if (entry.LastDefaultFactory != null) entry.DefaultFactories = (entry.DefaultFactories ?? HashTree<int, Factory>.Empty.AddOrUpdate(entry.MaxDefaultIndex++, entry.LastDefaultFactory)) .AddOrUpdate(entry.MaxDefaultIndex++, factory); entry.LastDefaultFactory = factory; } else if (serviceKey is int) { var index = (int)serviceKey; entry.DefaultFactories = (entry.DefaultFactories ?? HashTree<int, Factory>.Empty).AddOrUpdate(index, factory); entry.MaxDefaultIndex = Math.Max(entry.MaxDefaultIndex, index) + 1; } else if (serviceKey is string) { var name = (string)serviceKey; var named = entry.NamedFactories = entry.NamedFactories ?? new Dictionary<string, Factory>(); if (named.ContainsKey(name)) Throw.If(true, Error.DUPLICATE_SERVICE_NAME, serviceType, name, named[name].ImplementationType); named.Add(name, factory); } } return factory; }