private static IEnumerable ResolveMany(Type t, ResolutionPackage resolutionPackage)
 {
     foreach (Registration match in ResolveType(t))
     {
         foreach (object instance in Resolve(match, resolutionPackage))
         {
             yield return(instance);
         }
     }
 }
示例#2
0
        /// <summary>
        /// Creates an instance of the engine and copies the providers from the resolution package
        /// </summary>
        public Engine(ResolutionPackage resolutionPackage)
        {
            if (resolutionPackage is null)
            {
                throw new ArgumentNullException(nameof(resolutionPackage));
            }

            foreach (KeyValuePair <Type, AbstractServiceProvider> provider in resolutionPackage.ServiceProviders)
            {
                this.AllProviders.Add(provider.Key, provider.Value);
            }
        }
示例#3
0
        internal static object CreateRegisteredInstance(Registration registration, ResolutionPackage resolutionPackage, bool optional = false)
        {
            object toReturn = null;

            if (registration.InjectionFactory != null)
            {
                toReturn = registration.InjectionFactory.Invoke(Resolve <IServiceProvider>(resolutionPackage) ?? new Engine(resolutionPackage));
            }
            else if (registration.ToInstantiate != null && (!registration.ToInstantiate.IsInterface && !registration.ToInstantiate.IsAbstract))
            {
                toReturn = InstantiateObject(registration, resolutionPackage, optional);
            }

            if (toReturn != null)
            {
                ResolveProperties(toReturn, resolutionPackage);
            }

            return(toReturn);
        }
示例#4
0
        internal static bool IsResolvable(Type t, ResolutionPackage resolutionPackage)
        {
            if (ResolvableTypes.TryGetValue(t, out bool toReturn))
            {
                return(toReturn);
            }

            if (resolutionPackage.ResolutionPackageServices.ContainsKey(t))
            {
                return(true);
            }

            bool alreadyResolvable = IsValidIEnumerable(t) || ResolveType(t).Any();

            if (!alreadyResolvable)
            {
                if (typeof(ISelfRegistering).IsAssignableFrom(t))
                {
                    if (typeof(IRegisterMostDerived).IsAssignableFrom(t))
                    {
                        Type toRegister = TypeFactory.GetMostDerivedType(t);

                        RegisterAllBaseTypes(t, toRegister, typeof(TransientServiceProvider));
                    }
                    else
                    {
                        Register(t, t, typeof(TransientServiceProvider));
                    }
                    toReturn = true;
                }
            }
            else
            {
                toReturn = true;
            }

            ResolvableTypes.TryAdd(t, toReturn);

            return(toReturn);
        }
        private static object Resolve(Type t, ResolutionPackage resolutionPackage, bool optional = false)
        {
            if (t is null)
            {
                return(null);
            }

            if (IsValidIEnumerable(t, out Type collectionType))
            {
                IList toReturn = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(collectionType));

                foreach (object thisItem in ResolveMany(t, resolutionPackage))
                {
                    toReturn.Add(thisItem);
                }

                return(toReturn);
            }
            else
            {
                return(ResolveSingle(t, resolutionPackage, optional));
            }
        }
示例#6
0
        /// <summary>
        /// Resolves child properties of an object through the engine
        /// </summary>
        /// <typeparam name="T">Any class</typeparam>
        /// <param name="o">The object to resolve the properties of</param>
        /// <param name="resolutionPackage">Information to be used when resolving types</param>
        /// <returns>The passed in object with resolved properties (just in case)</returns>
        public static T ResolveProperties <T>(T o, ResolutionPackage resolutionPackage)
        {
            if (resolutionPackage is null)
            {
                throw new ArgumentNullException(nameof(resolutionPackage));
            }

            Type oType = o.GetType();

            if (!ChildDependencies.ContainsKey(oType))
            {
                ChildDependencies.TryAdd(oType, oType.GetProperties().Where(p => Attribute.IsDefined(p, typeof(DependencyAttribute))).ToList());
            }

            foreach (PropertyInfo thisDependency in ChildDependencies[oType])
            {
                if (!AnyRegistration(thisDependency.PropertyType))
                {
                    Type defaultType = thisDependency.GetCustomAttribute <DependencyAttribute>().Default;

                    thisDependency.SetValue(o, Resolve(
                                                new Registration()
                    {
                        ServiceProvider = typeof(TransientServiceProvider),
                        RegisteredType  = thisDependency.PropertyType,
                        ToInstantiate   = defaultType ?? thisDependency.PropertyType
                    }, resolutionPackage).SingleOrDefault());
                }
                else
                {
                    thisDependency.SetValue(o, Resolve(thisDependency.PropertyType, resolutionPackage, true));
                }
            }

            return(o);
        }
        private static IEnumerable <object> Resolve(Registration match, ResolutionPackage resolutionPackage, bool optional = false)
        {
            resolutionPackage.AddStack(match);

            //We resolve with that registration. Or attempt to
            if (!resolutionPackage.ServiceProviders.TryGetValue(match.ServiceProvider, out AbstractServiceProvider thisManager))
            {
                if (!resolutionPackage.ServiceProviders.TryGetValue(typeof(TransientServiceProvider), out thisManager))
                {
                    throw new Exception($"Type {match.ToInstantiate} could not be created because service provider of type {match.ServiceProvider} was not found in the current registrations and a transient service provider could not be found");
                }
                else
                {
                    StaticLogger.Log($"Type {match.ToInstantiate} created using transient service provider because {match.ServiceProvider} was not found in the current registrations", StaticLogger.LoggingLevel.Call);
                }
            }

            //If no registration was found, or there was no instance existing
            if (!(thisManager.GetService(match.ToInstantiate) is IList <object> toReturn) || !toReturn.Any())
            {
                //Create an instance
                toReturn = new List <object>();

                object o = CreateRegisteredInstance(match, resolutionPackage, optional);

                if (o != null)
                {
                    thisManager?.Add(match.ToInstantiate, o);
                    toReturn.Add(o);
                }
            }

            resolutionPackage.RemoveStack();

            return(toReturn);
        }
示例#8
0
        internal static object InstantiateObject(Registration registration, ResolutionPackage resolutionPackage, bool optional = false)
        {
            ConstructorInfo[] Constructors = registration.ToInstantiate.GetConstructors();

            foreach (ConstructorInfo thisConstructor in Constructors.OrderByDescending(c => c.GetParameters().Length))
            {
                ParameterInfo[] Parameters = thisConstructor.GetParameters();

                bool IsMatch = true;

                foreach (ParameterInfo thisParameter in Parameters)
                {
                    if (!IsResolvable(thisParameter.ParameterType, resolutionPackage) && !thisParameter.IsOptional)
                    {
                        IsMatch = false;
                        break;
                    }
                }

                if (IsMatch)
                {
                    object[] Params = Parameters.Select(p => Resolve(p.ParameterType, resolutionPackage)).ToArray();
                    return(Activator.CreateInstance(registration.ToInstantiate, Params));
                }
            }

            if (!optional)
            {
                StringBuilder registered = new StringBuilder();

                foreach (KeyValuePair <Type, ConcurrentList <Registration> > r in Engine.Registrations)
                {
                    registered.Append(r.Key.Name + System.Environment.NewLine);

                    foreach (Registration thisRegistration in r.Value)
                    {
                        registered.Append($"\t{thisRegistration.RegisteredType.FullName} => {thisRegistration.ToInstantiate.FullName} as {thisRegistration.ServiceProvider.FullName}");
                    }
                }

                MissingInjectableConstructorException exception = new MissingInjectableConstructorException(registration.ToInstantiate);

                string DebugText = registered.ToString();

                string Error = $"Type ({registration.ToInstantiate.FullName}) does not contain constructor with registered parameters...";

                foreach (ConstructorInfo constructor in Constructors)
                {
                    FailingConstructor failingConstructor = new FailingConstructor
                    {
                        Constructor       = constructor,
                        MissingParameters = constructor.GetParameters().Where(t => !IsRegistered(t.ParameterType)).ToArray()
                    };

                    Error += System.Environment.NewLine + string.Join(", ", constructor.GetParameters().Select(s => $"{s.ParameterType.FullName} {s.Name}"));
                    Error += System.Environment.NewLine + "Missing registrations: " + string.Join(", ", failingConstructor.MissingParameters.Select(s => $"{s.ParameterType.FullName} {s.Name}"));
                }

                exception.SetMessage(Error);

                throw exception;
            }
            else
            {
                return(null);
            }
        }
 private static T Resolve <T>(ResolutionPackage resolutionPackage) where T : class
 {
     return(Resolve(typeof(T), resolutionPackage) as T);
 }
        /// <summary>
        /// Returns a single instance of the type based on the LAST registration
        /// </summary>
        /// <param name="t">The type to return</param>
        /// <param name="resolutionPackage">A resolution package containing any providers</param>
        /// <param name="optional">Dont throw an error if its null</param>
        /// <returns>An instance of the requested type, if registered</returns>
        private static object ResolveSingle(Type t, ResolutionPackage resolutionPackage, bool optional = false)
        {
            if (!IsResolvable(t, resolutionPackage))
            {
                return(null);
            }

            if (resolutionPackage.ResolutionPackageServices.ContainsKey(t))
            {
                return(resolutionPackage.ResolutionPackageServices[t]);
            }

            //This whole IF block attempts to find a dependency consolidator for the requested type, and if its found it squishes all the registered instances into it
            //Which effectively allows for a class that converts an IEnumerable of a registered type into a single instance, which is great for things like providers
            //that may be registered independently but can be treated as a single unit through a consolidating class, that way everywhere the dependency is resolved
            //doesn't need to accept an IEnumerable of the types
            if (DependencyConsolidators.TryGetValue(t, out Type consolidatorType))
            {
                if (resolutionPackage.DependencyConsolidators.TryGetValue(t, out object consolidatedObject))
                {
                    return(consolidatedObject);
                }

                object consolidator;

                foreach (Registration reg in ResolveType(consolidatorType))
                {
                    if (!resolutionPackage.ServiceProviders.TryGetValue(reg.ServiceProvider, out AbstractServiceProvider provider))
                    {
                        provider = Activator.CreateInstance(reg.ServiceProvider) as AbstractServiceProvider;
                        resolutionPackage.ServiceProviders.Add(reg.ServiceProvider, provider);
                    }

                    consolidator = (provider.GetService(consolidatorType) as IList <object>)?.SingleOrDefault();

                    if (consolidator != null)
                    {
                        return(consolidator);
                    }
                }

                try
                {
                    consolidator = Activator.CreateInstance(consolidatorType);
                }
                catch (Exception ex)
                {
                    throw new Exception($"An error occured or creating and instance of the dependency consolidator type {consolidatorType}", ex);
                }

                IDeferredResolutionCollection deferredResolutionCollection = Activator.CreateInstance(typeof(DeferredResolutionCollection <>).MakeGenericType(t)) as IDeferredResolutionCollection;

                foreach (Registration reg in ResolveType(t))
                {
                    if (reg.ToInstantiate != consolidatorType)
                    {
                        deferredResolutionCollection.Add(() => Resolve(reg, resolutionPackage, optional).LastOrDefault());
                    }
                }

                MethodInfo setMethod = typeof(IConsolidateDependencies <>).MakeGenericType(t).GetMethod(nameof(IConsolidateDependencies <object> .Consolidate));

                consolidatedObject = setMethod.Invoke(consolidator, new object[] { deferredResolutionCollection });

                resolutionPackage.DependencyConsolidators.Add(t, consolidatedObject);

                foreach (Registration reg in ResolveType(consolidatorType))
                {
                    resolutionPackage.ServiceProviders[reg.ServiceProvider].Add(consolidatorType, consolidator);
                }

                return(consolidatedObject);
            }
            else
            {
                foreach (Registration reg in ResolveType(t))
                {
                    object toReturn = Resolve(reg, resolutionPackage, optional).LastOrDefault();

                    if (toReturn != null)
                    {
                        return(toReturn);
                    }
                }
            }

            return(null);
        }