private object ResolveObject(Type interfaceType, string shortName) { string key = GetKey(interfaceType.FullName, shortName); if (!map.ContainsKey(key)) { throw new Exception($"Service '{key}' is not registered"); } Type implementationType = map[key].TargetType; RegisteredService service = map[key]; switch (service.LifetimeType) { case LifetimeEnum.Singleton: // double check lock to ensure thread-safe if (service.SingletonInstance == null) { lock (service.SingletonMutex) { if (service.SingletonInstance == null) { object singletonObj = InitObject(key, implementationType); service.SingletonInstance = singletonObj; } } } return(service.SingletonInstance); case LifetimeEnum.Scope: // need to be thread safe object newScopedObj = InitObject(key, implementationType); object scopedObj = scopedObjMap.GetOrAdd(key, newScopedObj); return(scopedObj); case LifetimeEnum.Transient: return(InitObject(key, implementationType)); case LifetimeEnum.PerThread: object newPerThreadObj = InitObject(key, implementationType); string modifiedKey = $"{key}-{Thread.CurrentThread.ManagedThreadId}"; // this is not trictly correct. Thread can be reused. //CallContext.GetData(modifiedKey) object perThreadObj = perThreadObjMap.GetOrAdd(modifiedKey, newPerThreadObj); return(perThreadObj); default: return(null); } }
private void Register <TInterface, TImplementation>( LifetimeEnum lifetimeEnum, string shortName = null, object[] constParams = null ) where TImplementation : TInterface { string key = GetKey(typeof(TInterface).FullName, shortName); // define type and life scope map[key] = new RegisteredService() { LifetimeType = lifetimeEnum, TargetType = typeof(TImplementation) }; // enable constant constructor if (constParams != null) { paramMap[key] = constParams; } }