public static IEnumerable <Type> GetForKey(this RegisteredTypeContext ctx, object key = null) { if (key == null) { return(ctx.Where(t => !ctx.Keys.ContainsKey(t))); } return(ctx.Where(t => ctx.Keys.ContainsKey(t) && ReferenceEquals(ctx.Keys[t], key))); }
/// <summary> /// Resolves the constructor parameters. /// </summary> /// <param name="lifetimeScope">The lifetime scope.</param> /// <param name="ctx">The CTX.</param> /// <param name="constructorInfo">The constructor ctx.</param> /// <param name="arguments">The arguments.</param> /// <param name="additionalParameters"></param> /// <returns> /// True, if resolving constructor parameters succeed. /// </returns> /// <exception cref="System.ArgumentNullException"> /// constructorInfo /// or /// arguments /// </exception> private bool ResolveConstructorParameters(LifetimeScope lifetimeScope, RegisteredTypeContext ctx, MethodBase constructorInfo, ICollection <object> arguments, Parameter[] additionalParameters) { if (constructorInfo == null) { throw new ArgumentNullException("constructorInfo"); } if (arguments == null) { throw new ArgumentNullException("arguments"); } if (additionalParameters == null) { additionalParameters = new Parameter[0]; } arguments.Clear(); var outputType = constructorInfo.DeclaringType; var parameters = constructorInfo.GetParameters().OrderBy(x => x.Position); var declaredParameters = additionalParameters.Concat(ctx.Parameters.ContainsKey(outputType) ? ctx.Parameters[outputType] : Enumerable.Empty <Parameter>()); try { foreach (var parameterInfo in parameters) { var paramterResolved = false; foreach (var parameterCtx in declaredParameters.Where(parameterCtx => parameterCtx.IsApplicable(parameterInfo))) { arguments.Add(parameterCtx.GetValue(constructorInfo.DeclaringType)); paramterResolved = true; break; } if (paramterResolved) { continue; } var parameterInstance = this.Resolve(lifetimeScope, parameterInfo.ParameterType, outputType); arguments.Add(parameterInstance); } return(true); } catch (NotAssignableException) { arguments.Clear(); return(false); } }
private void ActivateInModules(RegisteredTypeContext ctx, Type target, object instance) { var moduleForType = ctx.Modules.ContainsKey(target) ? ctx.Modules[target] : null; foreach (var module in this.AllModules) { module.InstanceActivated(target, instance); if (moduleForType != null && moduleForType == module) { module.RegisteredInstanceActivated(target, instance); } } }
/// <summary> /// Builds this instance as IResolvable and check if type collection is correct. /// </summary> /// <returns>IResolvable instance</returns> public ILifetimeScope Build() { this.ModuleRegistration(); var resolvable = new Container { TypeContainer = new Dictionary <Type, RegisteredTypeContext>(), ResolveImplicit = this.ResolveImplicit, AllModules = this.modules.ToList() }; resolvable.RegisterResolver(cnt => new EnumerableResolver()); resolvable.RegisterResolver(cnt => new LazyResolver()); resolvable.RegisterResolver(cnt => new ContainerItselfResolver()); if (this.ActivatorEngine == null) { resolvable.ActivationEngine = data => Activator.CreateInstance(data.ResolvedType, data.ConstructorArguments.ToArray()); } else { resolvable.ActivationEngine = this.ActivatorEngine; } foreach (var nullType in this.typeContainer.Where(resolvableItem => resolvableItem.AsType == null).ToList()) { foreach (var inType in nullType.InTypes) { this.typeContainer.Add((new ItemRegistration(nullType.Origin, inType) { Scope = nullType.Scope }).As(inType)); } this.typeContainer.Remove(nullType); } foreach ( var builderResolvableItems in this.typeContainer .Where(resolvableItem => resolvableItem.AsType != null) .GroupBy(resolvableItem => resolvableItem.AsType)) { var notResolvable = builderResolvableItems.SelectMany(item => item.InTypes.Where(t => t.IsInterface || t.IsAbstract)) .FirstOrDefault(); if (notResolvable != null) { throw new NotAssignableException( notResolvable, $"Type \"{notResolvable.FullName}\" is abstract or interface so cannot be created."); } var ctx = new RegisteredTypeContext(resolvable, builderResolvableItems.Select(item => item.InTypes) .SelectMany(types => types) .ToList()); foreach (var builderResolvableItem in builderResolvableItems) { if (builderResolvableItem.OwnFactory != null) { ctx.OwnFactories = builderResolvableItem.InTypes.ToDictionary(type => type, type => builderResolvableItem.OwnFactory); } foreach (var type in builderResolvableItem.InTypes) { if (builderResolvableItem.Key != null) { ctx.Keys.Add(type, builderResolvableItem.Key); } foreach (var parameter in builderResolvableItem.Parameters) { if (!ctx.Parameters.ContainsKey(type)) { ctx.Parameters.Add(type, new HashSet <Parameter>(new[] { parameter })); } else { if (!ctx.Parameters[type].Add(parameter)) { throw new InvalidOperationException( "Cannot add parameter. The same already registered."); } } } } } foreach (var item in builderResolvableItems) { foreach (var inType in item.InTypes) { if (item.Module != null) { ctx.Modules.Add(inType, item.Module); } // TODO - key exist ctx.Scopes.Add(inType, item.Scope); } } var pair = new KeyValuePair <Type, RegisteredTypeContext>(builderResolvableItems.Key, ctx); resolvable.TypeContainer.Add(pair); } CheckForCycles(resolvable); GC.Collect(); return(resolvable); }
internal Scope WrapScope(LifetimeScope lifetimeScope, RegisteredTypeContext ctx, Scope desiredScope) { return(new ModuleDecorator(desiredScope, ctx, this.AllModules)); }
/// <summary> /// Creates the instance recursive. /// </summary> /// <param name="scope">The scope.</param> /// <param name="ctx">The CTX.</param> /// <param name="target">The target.</param> /// <param name="requestingType">Type of the requesting.</param> /// <param name="additionalParameters">Additional parameters to use for resolving</param> /// <returns></returns> /// <exception cref="NotAssignableException"></exception> internal object CreateInstanceRecursive(LifetimeScope scope, RegisteredTypeContext ctx, Type target, Type resolvedType, Type requestingType = null, params Parameter[] additionalParameters) { if (ctx.OwnFactories.ContainsKey(target)) { var inst = ctx.OwnFactories[target](new ActivationContext { ActivatedType = target, CurrentLifetimeScope = scope, RequestingType = requestingType }); if (inst == null) { throw new CannotResolveTypeException(target); } if (!resolvedType.IsAssignableFrom(inst.GetType())) { throw new CannotResolveTypeException(target); } return(inst); } if (target == typeof(object)) { throw new InvalidOperationException("Object type must have instance factory specified."); } LinkedList <object> constructorArguments = null; var constructors = target.GetConstructors(); ConstructorInfo ctor = null; if (constructors.Any()) { foreach (var constructorInfo in constructors) { var parametersInsance = new LinkedList <object>(); if (!this.ResolveConstructorParameters(scope, ctx, constructorInfo, parametersInsance, additionalParameters)) { continue; } constructorArguments = parametersInsance; ctor = constructorInfo; break; } } if (constructorArguments == null || ctor == null) { throw new NotAssignableException(target, $"There is no constructors in type \"{target.FullName}\""); } var instance = this.ActivationEngine( new ObjectActivatorData { ResolvedType = target, ConstructorInfo = ctor, ConstructorArguments = constructorArguments }); this.ActivateInModules(ctx, target, instance); scope.ScopeAllInstances.Add(instance); return(instance); }
public ModuleDecorator(Scope scope, RegisteredTypeContext typeContext, IEnumerable <Module> allModules) { this.typeContext = typeContext; this.allModules = allModules; this.scope = scope; }
/// <summary> /// Wraps the scope. /// </summary> /// <param name="lifetimeScope">The lifetime scope.</param> /// <param name="ctx">The CTX.</param> /// <param name="desiredScope">The desired scope.</param> /// <returns></returns> protected Scope WrapScope(LifetimeScope lifetimeScope, RegisteredTypeContext ctx, Scope desiredScope) { return(lifetimeScope.Container.WrapScope(lifetimeScope, ctx, desiredScope)); }