public void EnsureInitialized(ContainerService service, ContainerContext containerContext, ContainerService root) { if (!Owned) return; var componentInstance = Instance as IInitializable; if (componentInstance == null) return; if (!initialized) lock (this) if (!initialized) { var name = new ServiceName(Instance.GetType(), service.UsedContracts); if (containerContext.infoLogger != null) containerContext.infoLogger(name, "initialize started"); try { componentInstance.Initialize(); } catch (Exception e) { throw new SimpleContainerException(string.Format("exception initializing {0}\r\n\r\n{1}", name, root.GetConstructionLog(containerContext)), e); } if (containerContext.infoLogger != null) containerContext.infoLogger(name, "initialize finished"); initialized = true; } }
public ServiceDependency ServiceError(ContainerService service, string name = null) { return SetName(new ServiceDependency { Status = ServiceStatus.DependencyError, ContainerService = service }, null, name); }
public ServiceDependency NotResolved(ContainerService service, string name = null) { return SetName(new ServiceDependency { Status = ServiceStatus.NotResolved, ContainerService = service }, null, name); }
public ServiceDependency Service(ContainerService service, object value, string name = null) { return(SetName(new ServiceDependency { Status = ServiceStatus.Ok, Value = value, ContainerService = service }, null, name)); }
public ServiceDependency Service(ContainerService service, object value, string name = null) { return SetName(new ServiceDependency { Status = ServiceStatus.Ok, Value = value, ContainerService = service }, null, name); }
public bool TryGet(out ContainerService result) { if (value != null) { result = value; return true; } result = null; return false; }
public ServiceDependency Error(ContainerService containerService, string name, string message, params object[] args) { return(SetName(new ServiceDependency { ContainerService = containerService, Status = ServiceStatus.Error, Comment = string.Format(message, args) }, null, name)); }
public static ServiceDependency Error(ContainerService containerService, string name, string message, params object[] args) { return new ServiceDependency { ContainerService = containerService, Status = ServiceStatus.Error, Comment = string.Format(message, args) }.WithName(null, name); }
public bool TryGet(out ContainerService result) { if (value != null) { result = value; return(true); } result = null; return(false); }
public static bool TryCreate(ContainerService.Builder builder) { var factoryType = builder.Type.GetNestedType("Factory"); if (factoryType == null) return false; var method = factoryType.GetMethod("Create", Type.EmptyTypes); if (method == null) return false; var factory = builder.Context.Container.Resolve(method.DeclaringType, InternalHelpers.emptyStrings, false); if (factory.IsOk()) builder.CreateInstanceBy(CallTarget.M(method, factory.Single(), new object[0]), true); return true; }
public static bool TryCreate(ContainerService.Builder builder) { var factoryType = builder.Type.GetNestedType("Factory"); if (factoryType == null) return false; var method = factoryType.GetMethod("Create", Type.EmptyTypes); if (method == null) return false; var factory = builder.Context.Container.ResolveSingleton(method.DeclaringType, builder.Context); var dependency = factory.AsSingleInstanceDependency(null); builder.AddDependency(dependency, false); if (dependency.Status == ServiceStatus.Ok) builder.CreateInstance(method, dependency.Value, new object[0]); return true; }
private void PopResolutionContext(ResolutionContext.ResolutionContextActivation activation, ContainerService containerService, bool isEnumerable) { ResolutionContext.Pop(activation); if (activation.previous == null) { return; } var resultDependency = containerService.AsDependency(containerContext, "() => " + containerService.Type.FormatName(), isEnumerable); if (activation.activated.Container != activation.previous.Container) { resultDependency.Comment = "container boundary"; } activation.previous.TopBuilder.AddDependency(resultDependency, false); }
public bool AcquireInstantiateLock(out ContainerService service) { if (value != null) { service = value; return false; } Monitor.Enter(lockObject); if (value != null) { Monitor.Exit(lockObject); service = value; return false; } service = null; return true; }
public void LinkTo(ContainerContext containerContext, ContainerService childService, string comment) { var dependency = childService.AsDependency(containerContext, null, true); dependency.Comment = comment; AddDependency(dependency, true); UnionUsedContracts(childService); if (target.Status.IsGood()) { foreach (var instance in childService.Instances) { if (!instances.Contains(instance)) { AddInstance(instance); } } } }
internal object Create(ServiceName name, bool isEnumerable, object arguments) { Func <object> compiledFactory; var hasPendingResolutionContext = ResolutionContext.HasPendingResolutionContext; if (arguments == null && factoryCache.TryGetValue(name, out compiledFactory) && !hasPendingResolutionContext) { return(compiledFactory()); } var activation = ResolutionContext.Push(this); ContainerService result = null; List <string> oldContracts = null; try { if (hasPendingResolutionContext) { oldContracts = activation.activated.Contracts.Replace(name.Contracts); name = new ServiceName(name.Type); } result = ResolveCore(name, true, ObjectAccessor.Get(arguments), activation.activated); } finally { if (oldContracts != null) { activation.activated.Contracts.Restore(oldContracts); } PopResolutionContext(activation, result, isEnumerable); } if (!hasPendingResolutionContext) { result.EnsureInitialized(containerContext, result); } result.CheckStatusIsGood(containerContext); if (isEnumerable) { return(result.GetAllValues()); } result.CheckSingleValue(containerContext); return(result.Instances[0].Instance); }
public void EnsureInitialized(ContainerContext containerContext, ContainerService root) { if (Status != ServiceStatus.Ok) { return; } if (!initialized) { lock (lockObject) if (!initialized) { initializing = true; var oldInitializingService = threadInitializing; threadInitializing = true; try { if (dependencies != null) { foreach (var dependency in dependencies) { if (dependency.ContainerService != null) { dependency.ContainerService.EnsureInitialized(containerContext, root); } } } foreach (var instance in Instances) { instance.EnsureInitialized(this, containerContext, root); } initialized = true; } finally { initializing = false; threadInitializing = oldInitializingService; } } } }
public void EnsureInitialized(ContainerService service, ContainerContext containerContext, ContainerService root) { if (!Owned) { return; } var componentInstance = Instance as IInitializable; if (componentInstance == null) { return; } if (!initialized) { lock (this) if (!initialized) { var name = new ServiceName(Instance.GetType(), service.UsedContracts); if (containerContext.infoLogger != null) { containerContext.infoLogger(name, "initialize started"); } try { componentInstance.Initialize(); } catch (Exception e) { throw new SimpleContainerException( string.Format("exception initializing {0}\r\n\r\n{1}", name, root.GetConstructionLog(containerContext)), e); } if (containerContext.infoLogger != null) { containerContext.infoLogger(name, "initialize finished"); } initialized = true; } } }
public void UnionUsedContracts(ContainerService dependency) { if (dependency.UsedContracts == null) { return; } if (usedContractNames == null) { usedContractNames = new List <string>(); } foreach (var dependencyContract in dependency.UsedContracts) { if (usedContractNames.ContainsIgnoringCase(dependencyContract)) { continue; } string usedContractName = null; if (DeclaredContracts.ContainsIgnoringCase(dependencyContract)) { usedContractName = dependencyContract; } else if (ExpandedUnions.HasValue) { foreach (var c in ExpandedUnions.Value.unionedContracts) { if (c.children.ContainsIgnoringCase(dependencyContract)) { usedContractName = c.parent; break; } } } if (usedContractName != null) { usedContractNames.Add(usedContractName); } } }
public void WriteConstructionLog(ConstructionLogContext context) { context.WriteIndent(); if (ContainerService != null) { context.UsedFromDependency = this; ContainerService.WriteConstructionLog(context); return; } if (Status != ServiceStatus.Ok) { context.Writer.WriteMeta("!"); } context.Writer.WriteName(Name); if (Comment != null && Status != ServiceStatus.Error) { context.Writer.WriteMeta(" - "); context.Writer.WriteMeta(Comment); } if (Status == ServiceStatus.Ok && constantKind.HasValue) { if (constantKind == ConstantKind.Value) { ValueFormatter.WriteValue(context, Value, true); } if (constantKind == ConstantKind.Resource) { context.Writer.WriteMeta(string.Format(" resource [{0}]", resourceName)); } } if (Status == ServiceStatus.Error) { context.Writer.WriteMeta(" <---------------"); } context.Writer.WriteNewLine(); }
public void LinkTo(ContainerContext containerContext, ContainerService childService, string comment) { var dependency = childService.GetLinkedDependency(containerContext); dependency.Comment = comment; AddDependency(dependency, true); UnionUsedContracts(childService); if (target.Status.IsGood()) foreach (var instance in childService.instances) if (!instances.Contains(instance)) instances.Add(instance); }
public Builder(Type type, ResolutionContext context, bool createNew, IObjectAccessor arguments) { Arguments = arguments; CreateNew = createNew; target = new ContainerService {Type = type}; Context = context; DeclaredContracts = context.Contracts.ToArray(); try { Configuration = context.Container.GetConfiguration(Type, context); } catch (Exception e) { SetError(e); return; } SetComment(Configuration.Comment); foreach (var contract in Configuration.Contracts) { if (usedContractNames == null) usedContractNames = new List<string>(); if (!usedContractNames.Contains(contract, StringComparer.OrdinalIgnoreCase)) usedContractNames.Add(contract); } }
internal void Instantiate(ContainerService.Builder builder) { LifestyleAttribute lifestyle; if (builder.Type.IsSimpleType()) builder.SetError("can't create simple type"); else if (builder.Type == typeof (IContainer)) builder.AddInstance(this, false); else if (builder.Configuration.ImplementationAssigned) builder.AddInstance(builder.Configuration.Implementation, builder.Configuration.ContainerOwnsInstance); else if (builder.Configuration.Factory != null) builder.CreateInstanceBy(() => builder.Configuration.Factory(this), builder.Configuration.ContainerOwnsInstance); else if (builder.Configuration.FactoryWithTarget != null) { if (!builder.Context.AnalizeDependenciesOnly) { var previousService = builder.Context.GetPreviousBuilder(); var target = previousService == null ? null : previousService.Type; builder.CreateInstanceBy(() => builder.Configuration.FactoryWithTarget(this, target), builder.Configuration.ContainerOwnsInstance); } } else if (builder.Type.IsValueType) builder.SetError("can't create value type"); else if (builder.Type.IsGenericType && builder.Type.ContainsGenericParameters) builder.SetError("can't create open generic"); else if (!builder.CreateNew && builder.Type.TryGetCustomAttribute(out lifestyle) && lifestyle.Lifestyle == Lifestyle.PerRequest) { const string messageFormat = "service [{0}] with PerRequest lifestyle can't be resolved, use Func<{0}> instead"; builder.SetError(string.Format(messageFormat, builder.Type.FormatName())); } else if (builder.Type.IsAbstract) InstantiateInterface(builder); else InstantiateImplementation(builder); if (builder.Configuration.InstanceFilter != null) { var filteredOutCount = builder.FilterInstances(builder.Configuration.InstanceFilter); if (filteredOutCount > 0) builder.SetComment("instance filter"); } }
private void InstantiateImplementation(ContainerService.Builder builder) { if (builder.DontUse()) { builder.SetComment("DontUse"); return; } var result = FactoryCreator.TryCreate(builder) ?? LazyCreator.TryCreate(builder); if (result != null) { builder.AddInstance(result, true); return; } if (NestedFactoryCreator.TryCreate(builder)) return; if (CtorFactoryCreator.TryCreate(builder)) return; if (builder.Type.IsDelegate()) { builder.SetError(string.Format("can't create delegate [{0}]", builder.Type.FormatName())); return; } var constructor = builder.Type.GetConstructor(); if (!constructor.isOk) { builder.SetError(constructor.errorMessage); return; } var formalParameters = constructor.value.GetParameters(); var actualArguments = new object[formalParameters.Length]; var hasServiceNameParameters = false; for (var i = 0; i < formalParameters.Length; i++) { var formalParameter = formalParameters[i]; if (formalParameter.ParameterType == typeof (ServiceName)) { hasServiceNameParameters = true; continue; } var dependency = InstantiateDependency(formalParameter, builder).CastTo(formalParameter.ParameterType); builder.AddDependency(dependency, false); if (dependency.ContainerService != null) builder.UnionUsedContracts(dependency.ContainerService); if (builder.Status != ServiceStatus.Ok && !builder.Context.AnalizeDependenciesOnly) return; actualArguments[i] = dependency.Value; } foreach (var d in builder.Configuration.ImplicitDependencies) { var dependency = builder.Context.Resolve(d).AsSingleInstanceDependency(null); dependency.Comment = "implicit"; builder.AddDependency(dependency, false); if (dependency.ContainerService != null) builder.UnionUsedContracts(dependency.ContainerService); if (builder.Status != ServiceStatus.Ok) return; } builder.EndResolveDependencies(); if (builder.Context.AnalizeDependenciesOnly) return; var dependenciesResolvedByArguments = builder.Arguments == null ? InternalHelpers.emptyStrings : builder.Arguments.GetUsed().Select(InternalHelpers.ByNameDependencyKey); var unusedConfigurationKeys = builder.Configuration.GetUnusedDependencyConfigurationKeys() .Except(dependenciesResolvedByArguments) .ToArray(); if (unusedConfigurationKeys.Length > 0) { builder.SetError(string.Format("unused dependency configurations [{0}]", unusedConfigurationKeys.JoinStrings(","))); return; } if (hasServiceNameParameters) for (var i = 0; i < formalParameters.Length; i++) if (formalParameters[i].ParameterType == typeof (ServiceName)) actualArguments[i] = builder.GetName(); if (builder.CreateNew || builder.DeclaredContracts.Length == builder.FinalUsedContracts.Length) { builder.CreateInstance(constructor.value, null, actualArguments); if (builder.CreateNew && builder.Arguments == null) { var compiledConstructor = constructor.value.Compile(); factoryCache.TryAdd(builder.GetName(), () => { var instance = compiledConstructor(null, actualArguments); var component = instance as IInitializable; if (component != null) component.Initialize(); return instance; }); } return; } var serviceForUsedContractsId = instanceCache.GetOrAdd(builder.GetName(), createId); ContainerService serviceForUsedContracts; if (serviceForUsedContractsId.AcquireInstantiateLock(out serviceForUsedContracts)) { builder.CreateInstance(constructor.value, null, actualArguments); serviceForUsedContracts = builder.Build(); serviceForUsedContractsId.ReleaseInstantiateLock(builder.Context.AnalizeDependenciesOnly ? null : serviceForUsedContracts); } else builder.Reuse(serviceForUsedContracts); }
public void Reuse(ContainerService containerService) { target = containerService; built = true; }
public void ReleaseInstantiateLock(ContainerService result) { value = result; Monitor.Exit(lockObject); }
private void InstantiateInterface(ContainerService.Builder builder) { var implementationTypes = GetImplementationTypes(builder); ApplySelectors(implementationTypes, builder); if (implementationTypes.Count == 0) { builder.SetComment("has no implementations"); return; } Func<object> factory = null; var canUseFactory = true; foreach (var implementationType in implementationTypes) if (implementationType.accepted) { var implementationService = builder.CreateNew ? builder.Context.Instantiate(implementationType.type, true, builder.Arguments) : builder.Context.Resolve(ServiceName.Parse(implementationType.type, false)); builder.LinkTo(containerContext, implementationService, implementationType.comment); if (builder.CreateNew && builder.Arguments == null && implementationService.Status == ServiceStatus.Ok && canUseFactory) if (factory == null) { if (!factoryCache.TryGetValue(implementationService.Name, out factory)) canUseFactory = false; } else canUseFactory = false; if (builder.Status.IsBad()) return; } else { var dependency = ServiceDependency.NotResolved(null, implementationType.type.FormatName()); dependency.Comment = implementationType.comment; builder.AddDependency(dependency, true); } builder.EndResolveDependencies(); if (factory != null && canUseFactory) factoryCache.TryAdd(builder.GetName(), factory); }
private void InstantiateInterface(ContainerService.Builder builder) { HashSet<ImplementationType> implementationTypes; try { implementationTypes = GetImplementationTypes(builder); } catch (Exception e) { builder.SetError(e); return; } ApplySelectors(implementationTypes, builder); if (implementationTypes.Count == 0) { builder.SetComment("has no implementations"); return; } Func<object> factory = null; var canUseFactory = true; foreach (var implementationType in implementationTypes) if (implementationType.accepted) { var implementationService = ResolveCore(ServiceName.Parse(implementationType.type, InternalHelpers.emptyStrings), builder.CreateNew, builder.Arguments, builder.Context); builder.LinkTo(containerContext, implementationService, implementationType.comment); if (builder.CreateNew && builder.Arguments == null && implementationService.Status == ServiceStatus.Ok && canUseFactory) if (factory == null) { if (!factoryCache.TryGetValue(implementationService.Name, out factory)) canUseFactory = false; } else canUseFactory = false; if (builder.Status.IsBad()) return; } else { var dependency = containerContext.NotResolved(null, implementationType.type.FormatName()); dependency.Comment = implementationType.comment; builder.AddDependency(dependency, true); } builder.EndResolveDependencies(); if (factory != null && canUseFactory) factoryCache.TryAdd(builder.GetFinalName(), factory); }
private void PopResolutionContext(ResolutionContext.ResolutionContextActivation activation, ContainerService containerService, bool isEnumerable) { ResolutionContext.Pop(activation); if (activation.previous == null) return; var resultDependency = containerService.AsDependency(containerContext, "() => " + containerService.Type.FormatName(),isEnumerable); if (activation.activated.Container != activation.previous.Container) resultDependency.Comment = "container boundary"; activation.previous.TopBuilder.AddDependency(resultDependency, false); }
private void InstantiateImplementation(ContainerService.Builder builder) { if (builder.DontUse()) { builder.SetComment("DontUse"); return; } var result = FactoryCreator.TryCreate(builder) ?? LazyCreator.TryCreate(builder); if (result != null) { builder.AddInstance(result, true, false); return; } if (NestedFactoryCreator.TryCreate(builder)) return; if (CtorFactoryCreator.TryCreate(builder)) return; if (builder.Type.IsDelegate()) { builder.SetError(string.Format("can't create delegate [{0}]", builder.Type.FormatName())); return; } var constructor = builder.Type.GetConstructor(); if (!constructor.isOk) { builder.SetError(constructor.errorMessage); return; } var formalParameters = constructor.value.GetParameters(); var actualArguments = new object[formalParameters.Length]; var hasServiceNameParameters = false; for (var i = 0; i < formalParameters.Length; i++) { var formalParameter = formalParameters[i]; if (formalParameter.ParameterType == typeof (ServiceName)) { hasServiceNameParameters = true; continue; } var dependency = InstantiateDependency(formalParameter, builder).CastTo(formalParameter.ParameterType); builder.AddDependency(dependency, false); if (dependency.ContainerService != null) builder.UnionUsedContracts(dependency.ContainerService); if (builder.Status != ServiceStatus.Ok && !builder.Context.AnalizeDependenciesOnly) return; actualArguments[i] = dependency.Value; } foreach (var d in builder.Configuration.ImplicitDependencies) { var dependency = ResolveCore(ServiceName.Parse(d.Type, d.Contracts), false, null, builder.Context) .AsDependency(containerContext, null, false); dependency.Comment = "implicit"; builder.AddDependency(dependency, false); if (dependency.ContainerService != null) builder.UnionUsedContracts(dependency.ContainerService); if (builder.Status != ServiceStatus.Ok) return; } builder.EndResolveDependencies(); if (builder.Context.AnalizeDependenciesOnly) return; var dependenciesResolvedByArguments = builder.Arguments == null ? null : builder.Arguments.GetUsed(); List<string> unusedConfigurationKeys = null; foreach (var k in builder.Configuration.GetUnusedDependencyKeys()) { var resolvedByArguments = dependenciesResolvedByArguments != null && k.name != null && dependenciesResolvedByArguments.Contains(k.name); if (resolvedByArguments) continue; if (unusedConfigurationKeys == null) unusedConfigurationKeys = new List<string>(); unusedConfigurationKeys.Add(k.ToString()); } if (unusedConfigurationKeys != null) { builder.SetError(string.Format("unused dependency configurations [{0}]", unusedConfigurationKeys.JoinStrings(","))); return; } if (hasServiceNameParameters) for (var i = 0; i < formalParameters.Length; i++) if (formalParameters[i].ParameterType == typeof (ServiceName)) actualArguments[i] = builder.GetFinalName(); if (builder.CreateNew || builder.DeclaredContracts.Length == builder.FinalUsedContracts.Length) { builder.CreateInstanceBy(CallTarget.M(constructor.value, null, actualArguments), true); if (builder.CreateNew && builder.Arguments == null) { var compiledConstructor = constructor.value.Compile(); factoryCache.TryAdd(builder.GetFinalName(), () => { var instance = compiledConstructor(null, actualArguments); var component = instance as IInitializable; if (component != null) component.Initialize(); return instance; }); } return; } var serviceForUsedContractsId = instanceCache.GetOrAdd(builder.GetFinalName(), createId); var acquireResult = serviceForUsedContractsId.AcquireInstantiateLock(); if (acquireResult.acquired) { builder.CreateInstanceBy(CallTarget.M(constructor.value, null, actualArguments), true); serviceForUsedContractsId.ReleaseInstantiateLock(builder.Context.AnalizeDependenciesOnly ? null : builder.GetService()); } else builder.Reuse(acquireResult.alreadyConstructedService); }
private HashSet<ImplementationType> GetImplementationTypes(ContainerService.Builder builder) { var result = new HashSet<ImplementationType>(); var candidates = builder.Configuration.ImplementationTypes ?? containerContext.typesList.InheritorsOf(builder.Type.GetDefinition()); var implementationTypesAreExplicitlyConfigured = builder.Configuration.ImplementationTypes != null; foreach (var implType in candidates) { if (!implementationTypesAreExplicitlyConfigured) { var configuration = GetConfiguration(implType, builder.Context); if (configuration.IgnoredImplementation || implType.IsDefined("IgnoredImplementationAttribute")) result.Add(new ImplementationType { type = implType, comment = "IgnoredImplementation", accepted = false }); } if (!implType.IsGenericType) { if (!builder.Type.IsGenericType || builder.Type.IsAssignableFrom(implType)) result.Add(ImplementationType.Accepted(implType)); } else if (!implType.ContainsGenericParameters) result.Add(ImplementationType.Accepted(implType)); else { var mapped = containerContext.genericsAutoCloser.AutoCloseDefinition(implType); foreach (var type in mapped) if (builder.Type.IsAssignableFrom(type)) result.Add(ImplementationType.Accepted(type)); if (builder.Type.IsGenericType) { var implInterfaces = implType.ImplementationsOf(builder.Type.GetGenericTypeDefinition()); foreach (var implInterface in implInterfaces) { var closed = implType.TryCloseByPattern(implInterface, builder.Type); if (closed != null) result.Add(ImplementationType.Accepted(closed)); } } if (builder.Arguments == null) continue; var serviceConstructor = implType.GetConstructor(); if (!serviceConstructor.isOk) continue; foreach (var formalParameter in serviceConstructor.value.GetParameters()) { if (!formalParameter.ParameterType.ContainsGenericParameters) continue; ValueWithType parameterValue; if (!builder.Arguments.TryGet(formalParameter.Name, out parameterValue)) continue; var parameterType = parameterValue.value == null ? parameterValue.type : parameterValue.value.GetType(); var implInterfaces = formalParameter.ParameterType.IsGenericParameter ? new List<Type>(1) {parameterType} : parameterType.ImplementationsOf(formalParameter.ParameterType.GetGenericTypeDefinition()); foreach (var implInterface in implInterfaces) { var closedItem = implType.TryCloseByPattern(formalParameter.ParameterType, implInterface); if (closedItem != null) result.Add(ImplementationType.Accepted(closedItem)); } } } } return result; }
public void Reuse(ContainerService containerService) { target = containerService; reused = true; }
public void EnsureInitialized(ContainerContext containerContext, ContainerService root) { if (Status != ServiceStatus.Ok) return; if (!initialized) lock (lockObject) if (!initialized) { initializing = true; try { if (dependencies != null) foreach (var dependency in dependencies) if (dependency.ContainerService != null) dependency.ContainerService.EnsureInitialized(containerContext, root); foreach (var instance in instances) instance.EnsureInitialized(this, containerContext, root); initialized = true; } finally { initializing = false; } } }
public void UnionUsedContracts(ContainerService dependency) { if (dependency.UsedContracts == null) return; if (usedContractNames == null) usedContractNames = new List<string>(); var contractsToAdd = dependency.UsedContracts .Where(x => !usedContractNames.Contains(x, StringComparer.OrdinalIgnoreCase)) .Where(x => DeclaredContracts.Any(x.EqualsIgnoringCase)); foreach (var n in contractsToAdd) usedContractNames.Add(n); }
internal void Instantiate(ContainerService.Builder builder) { LifestyleAttribute lifestyle; if (builder.Type.IsSimpleType()) builder.SetError("can't create simple type"); else if (builder.Type == typeof (IContainer)) builder.AddInstance(this, false, false); else if (builder.Configuration.ImplementationAssigned) builder.AddInstance(builder.Configuration.Implementation, builder.Configuration.ContainerOwnsInstance, true); else if (builder.Configuration.Factory != null) { if (!builder.Context.AnalizeDependenciesOnly) builder.CreateInstanceBy(CallTarget.F(builder.Configuration.Factory), builder.Configuration.ContainerOwnsInstance); } else if (builder.Type.IsValueType) builder.SetError("can't create value type"); else if (builder.Type.IsGenericType && builder.Type.ContainsGenericParameters) builder.SetError("can't create open generic"); else if (!builder.CreateNew && builder.Type.TryGetCustomAttribute(out lifestyle) && lifestyle.Lifestyle == Lifestyle.PerRequest) { const string messageFormat = "service [{0}] with PerRequest lifestyle can't be resolved, use Func<{0}> instead"; builder.SetError(string.Format(messageFormat, builder.Type.FormatName())); } else if (builder.Type.IsAbstract) InstantiateInterface(builder); else InstantiateImplementation(builder); }
public static bool TryCreate(ContainerService.Builder builder) { if (!builder.Type.IsDelegate()) return false; if (!builder.Type.IsNestedPublic) return false; var invokeMethod = builder.Type.GetMethod("Invoke"); if (invokeMethod.ReturnType != builder.Type.DeclaringType) return false; var constructor = builder.Type.DeclaringType.GetConstructor(); if (!constructor.isOk) { builder.SetError(constructor.errorMessage); return true; } var delegateParameters = invokeMethod.GetParameters(); var delegateParameterNameToIndexMap = new Dictionary<string, int>(); for (var i = 0; i < delegateParameters.Length; i++) delegateParameterNameToIndexMap[delegateParameters[i].Name] = i; var dynamicMethodParameterTypes = new Type[delegateParameters.Length + 1]; dynamicMethodParameterTypes[0] = typeof (object[]); for (var i = 1; i < dynamicMethodParameterTypes.Length; i++) dynamicMethodParameterTypes[i] = delegateParameters[i - 1].ParameterType; var dynamicMethod = new DynamicMethod("", invokeMethod.ReturnType, dynamicMethodParameterTypes, typeof (ReflectionHelpers), true); var il = dynamicMethod.GetILGenerator(); var ctorParameters = constructor.value.GetParameters(); var notBoundCtorParameters = ctorParameters .Where(x => x.ParameterType.IsSimpleType() && !delegateParameterNameToIndexMap.ContainsKey(x.Name)) .Select(x => x.Name) .ToArray(); if (notBoundCtorParameters.Length > 0) { builder.SetError(string.Format("ctor has not bound parameters [{0}]", notBoundCtorParameters.JoinStrings(","))); return true; } var serviceTypeToIndex = new Dictionary<Type, int>(); var services = new List<object>(); foreach (var p in ctorParameters) { int delegateParameterIndex; if (delegateParameterNameToIndexMap.TryGetValue(p.Name, out delegateParameterIndex)) { var delegateParameterType = delegateParameters[delegateParameterIndex].ParameterType; if (!p.ParameterType.IsAssignableFrom(delegateParameterType)) { const string messageFormat = "type mismatch for [{0}], delegate type [{1}], ctor type [{2}]"; builder.SetError(string.Format(messageFormat, p.Name, delegateParameterType.FormatName(), p.ParameterType.FormatName())); return true; } il.EmitLdArg(delegateParameterIndex + 1); delegateParameterNameToIndexMap.Remove(p.Name); } else { int serviceIndex; if (!serviceTypeToIndex.TryGetValue(p.ParameterType, out serviceIndex)) { object value; if (p.ParameterType == typeof (ServiceName)) value = null; else { var dependency = builder.Context.Container.InstantiateDependency(p, builder).CastTo(p.ParameterType); builder.AddDependency(dependency, false); if (dependency.ContainerService != null) builder.UnionUsedContracts(dependency.ContainerService); if (builder.Status != ServiceStatus.Ok) return true; value = dependency.Value; } serviceIndex = serviceTypeToIndex.Count; serviceTypeToIndex.Add(p.ParameterType, serviceIndex); services.Add(value); } il.Emit(OpCodes.Ldarg_0); il.EmitLdInt32(serviceIndex); il.Emit(OpCodes.Ldelem_Ref); il.Emit(p.ParameterType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, p.ParameterType); } } if (delegateParameterNameToIndexMap.Count > 0) { builder.SetError(string.Format("delegate has not used parameters [{0}]", delegateParameterNameToIndexMap.Keys.JoinStrings(","))); return true; } builder.EndResolveDependencies(); int serviceNameIndex; if (serviceTypeToIndex.TryGetValue(typeof (ServiceName), out serviceNameIndex)) services[serviceNameIndex] = new ServiceName(builder.Type.DeclaringType, builder.FinalUsedContracts); il.Emit(OpCodes.Newobj, constructor.value); il.Emit(OpCodes.Ret); var context = serviceTypeToIndex.Count == 0 ? null : services.ToArray(); builder.AddInstance(dynamicMethod.CreateDelegate(builder.Type, context), true); return true; }
internal ServiceDependency InstantiateDependency(ParameterInfo formalParameter, ContainerService.Builder builder) { ValueWithType actualArgument; if (builder.Arguments != null && builder.Arguments.TryGet(formalParameter.Name, out actualArgument)) return containerContext.Constant(formalParameter, actualArgument.value); var parameters = builder.Configuration.ParametersSource; object actualParameter; if (parameters != null && parameters.TryGet(formalParameter.Name, formalParameter.ParameterType, out actualParameter)) return containerContext.Constant(formalParameter, actualParameter); var dependencyConfiguration = builder.Configuration.GetOrNull(formalParameter); Type implementationType = null; if (dependencyConfiguration != null) { if (dependencyConfiguration.ValueAssigned) return containerContext.Constant(formalParameter, dependencyConfiguration.Value); if (dependencyConfiguration.Factory != null) { var dependencyBuilder = new ContainerService.Builder(new ServiceName(formalParameter.ParameterType)) { Context = builder.Context, DependencyName = formalParameter.Name }; builder.Context.Stack.Add(dependencyBuilder); dependencyBuilder.CreateInstanceBy(CallTarget.F(dependencyConfiguration.Factory), true); builder.Context.Stack.RemoveLast(); return dependencyBuilder.GetService().AsDependency(containerContext, formalParameter.Name, false); } implementationType = dependencyConfiguration.ImplementationType; } implementationType = implementationType ?? formalParameter.ParameterType; FromResourceAttribute resourceAttribute; if (implementationType == typeof (Stream) && formalParameter.TryGetCustomAttribute(out resourceAttribute)) { var resourceStream = builder.Type.Assembly.GetManifestResourceStream(builder.Type, resourceAttribute.Name); if (resourceStream == null) return containerContext.Error(null, formalParameter.Name, "can't find resource [{0}] in namespace of [{1}], assembly [{2}]", resourceAttribute.Name, builder.Type, builder.Type.Assembly.GetName().Name); return containerContext.Resource(formalParameter, resourceAttribute.Name, resourceStream); } var dependencyName = ServiceName.Parse(implementationType.UnwrapEnumerable(), InternalHelpers.ParseContracts(formalParameter)); if (dependencyName.Type.IsSimpleType()) { if (!formalParameter.HasDefaultValue) return containerContext.Error(null, formalParameter.Name, "parameter [{0}] of service [{1}] is not configured", formalParameter.Name, builder.Type.FormatName()); return containerContext.Constant(formalParameter, formalParameter.DefaultValue); } var resultService = ResolveCore(dependencyName, false, null, builder.Context); if (resultService.Status.IsBad()) return containerContext.ServiceError(resultService); var isEnumerable = dependencyName.Type != implementationType; if (isEnumerable) return containerContext.Service(resultService, resultService.GetAllValues()); if (resultService.Status == ServiceStatus.NotResolved) { if (formalParameter.HasDefaultValue) return containerContext.Service(resultService, formalParameter.DefaultValue); if (formalParameter.IsDefined<OptionalAttribute>() || formalParameter.IsDefined("CanBeNullAttribute")) return containerContext.Service(resultService, null); return containerContext.NotResolved(resultService); } return resultService.AsDependency(containerContext, null, false); }
internal ContainerService ResolveCore(ServiceName name, bool createNew, IObjectAccessor arguments, ResolutionContext context) { var pushedContracts = context.Contracts.Push(name.Contracts); var declaredName = new ServiceName(name.Type, context.Contracts.Snapshot()); if (context.HasCycle(declaredName)) { var message = string.Format("cyclic dependency for service [{0}], stack\r\n{1}", declaredName.Type.FormatName(), context.FormatStack() + "\r\n\t" + declaredName); context.Contracts.RemoveLast(pushedContracts.pushedContractsCount); return(ContainerService.Error(declaredName, message)); } if (!pushedContracts.isOk) { const string messageFormat = "contract [{0}] already declared, stack\r\n{1}"; var message = string.Format(messageFormat, pushedContracts.duplicatedContractName, context.FormatStack() + "\r\n\t" + name); context.Contracts.RemoveLast(pushedContracts.pushedContractsCount); return(ContainerService.Error(name, message)); } context.ConstructingServices.Add(declaredName); ServiceConfiguration configuration = null; Exception configurationException = null; try { configuration = GetConfiguration(declaredName.Type, context); } catch (Exception e) { configurationException = e; } var actualName = configuration != null && configuration.FactoryDependsOnTarget && context.Stack.Count > 0 ? declaredName.AddContracts(context.TopBuilder.Type.FormatName()) : declaredName; ContainerServiceId id = null; if (!createNew) { id = instanceCache.GetOrAdd(actualName, createId); var acquireResult = id.AcquireInstantiateLock(); if (!acquireResult.acquired) { context.ConstructingServices.Remove(declaredName); context.Contracts.RemoveLast(pushedContracts.pushedContractsCount); return(acquireResult.alreadyConstructedService); } } var builder = new ContainerService.Builder(actualName); context.Stack.Add(builder); builder.Context = context; builder.DeclaredContracts = actualName.Contracts; if (configuration == null) { builder.SetError(configurationException); } else { builder.SetConfiguration(configuration); builder.ExpandedUnions = context.Contracts.TryExpandUnions(Configuration); if (builder.ExpandedUnions.HasValue) { var poppedContracts = context.Contracts.PopMany(builder.ExpandedUnions.Value.contracts.Length); foreach (var c in builder.ExpandedUnions.Value.contracts.CartesianProduct()) { var childService = ResolveCore(new ServiceName(name.Type, c), createNew, arguments, context); builder.LinkTo(containerContext, childService, null); if (builder.Status.IsBad()) { break; } } context.Contracts.PushNoCheck(poppedContracts); } else { builder.CreateNew = createNew; builder.Arguments = arguments; Instantiate(builder); } } context.ConstructingServices.Remove(declaredName); context.Contracts.RemoveLast(pushedContracts.pushedContractsCount); context.Stack.RemoveLast(); var result = builder.GetService(); if (id != null) { id.ReleaseInstantiateLock(builder.Context.AnalizeDependenciesOnly ? null : result); } return(result); }
private void ApplySelectors(HashSet<ImplementationType> implementations, ContainerService.Builder builder) { if (builder.Configuration != ServiceConfiguration.empty) return; if (implementationSelectors.Count == 0) return; var selectorDecisions = new List<ImplementationSelectorDecision>(); var typesArray = implementations.Select(x => x.type).ToArray(); foreach (var s in implementationSelectors) s(builder.Type, typesArray, selectorDecisions); foreach (var decision in selectorDecisions) { var item = new ImplementationType { type = decision.target, comment = decision.comment, accepted = decision.action == ImplementationSelectorDecision.Action.Include }; implementations.Replace(item); } }