/// <summary>
 /// Registers a dependency
 /// </summary>
 /// <typeparam name="TDependency">The interface / base class of the dependency</typeparam>
 /// <typeparam name="TImplementation">The implementation class to use</typeparam>
 public static void Register <TDependency, TImplementation>()
     where TDependency : class
     where TImplementation : TDependency
 {
     lock (dependencyLock)
     {
         if (dependencies.ContainsKey(typeof(TDependency)))
         {
             throw new AlreadyRegisteredDependencyException(typeof(TDependency)); // dependency already registered
         }
         dependencies[typeof(TDependency)] = new TranscientDependencyData
         {
             ImplementationType = typeof(TImplementation),
         };
     }
 }
예제 #2
0
        private void GetConstructorInfo(TranscientDependencyData dependencyData)
        {
            var constructors = dependencyData.ImplementationType.GetConstructors();

            if (constructors.Length == 0)
            {
                throw new ImplementationNotInstanciableException(dependencyData.ImplementationType);
            }

            dependencyData.ConstructorInfo = TryGetFirstEligibleConstructor(dependencyData);

            if (dependencyData.ConstructorInfo is null)
            {
                throw new NoSuitableConstructorFoundException(dependencyData.ImplementationType);
            }
        }
예제 #3
0
        /// <summary>
        /// Resovles a dependency using the type of the dependency interface / base class
        /// </summary>
        /// <param name="dependencyData">The data containing the implementation type and, if already resolved, the constructor</param>
        /// <param name="dependencyLock">Locks the dependency service to ensure if to be thread safe</param>
        /// <returns></returns>
        public object Resolve(TranscientDependencyData dependencyData, object dependencyLock)
        {
            // lock the dependency service for it to be thread safe
            // Getting the constructor info modifies the DependencyService
            // the lock avoid collision and doing the same thing twice.
            lock (dependencyLock)
            {
                if (dependencyData.ConstructorInfo is null)
                {
                    GetConstructorInfo(dependencyData);
                }
            }
            // Release the lock as soon and possible
            // Construct(DependencyData) will not modify the DependencyInjectionService

            return(Construct(dependencyData));
        }
예제 #4
0
        private object Construct(TranscientDependencyData dependencyData)
        {
            var           parameters            = dependencyData.ConstructorInfo.GetParameters();
            List <object> constructorParameters = new List <object>();

            try
            {
                foreach (var parameter in parameters)
                {
                    var paramType = parameter.ParameterType;
                    constructorParameters.Add(DependencyInjectionService.Resolve(paramType));
                }

                return(Activator.CreateInstance(dependencyData.ImplementationType, constructorParameters.ToArray()));
            }
            catch (NotRegisteredDependencyException)
            {
                return(null);
            }
        }
예제 #5
0
        private ConstructorInfo TryGetFirstEligibleConstructor(TranscientDependencyData dependencyData)
        {
            foreach (var constructor in dependencyData.ImplementationType.GetConstructors())
            {
                var eligible = true;
                foreach (var parameter in constructor.GetParameters())
                {
                    if (!DependencyInjectionService.IsRegistered(parameter.ParameterType))
                    {
                        eligible = false;
                        break;
                    }
                }

                if (eligible)
                {
                    return(constructor);
                }
            }

            return(null);
        }
예제 #6
0
 /// <summary>
 /// Resovles a dependency using the generic as dependency interface / base class
 /// </summary>
 /// <typeparam name="TDependency">the dependency interface / base class</typeparam>
 /// <param name="dependencyData">The data containing the implementation type and, if already resolved, the constructor</param>
 /// <param name="dependencyLock">Locks the dependency service to ensure if to be thread safe</param>
 /// <returns></returns>
 public TDependency Resolve <TDependency>(TranscientDependencyData dependencyData, object dependencyLock)
 {
     return((TDependency)Resolve(dependencyData, dependencyLock));
 }