コード例 #1
0
 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;
             }
 }
コード例 #2
0
 public ServiceDependency ServiceError(ContainerService service, string name = null)
 {
     return SetName(new ServiceDependency
     {
         Status = ServiceStatus.DependencyError,
         ContainerService = service
     }, null, name);
 }
コード例 #3
0
 public ServiceDependency NotResolved(ContainerService service, string name = null)
 {
     return SetName(new ServiceDependency
     {
         Status = ServiceStatus.NotResolved,
         ContainerService = service
     }, null, name);
 }
コード例 #4
0
 public ServiceDependency Service(ContainerService service, object value, string name = null)
 {
     return(SetName(new ServiceDependency
     {
         Status = ServiceStatus.Ok,
         Value = value,
         ContainerService = service
     }, null, name));
 }
コード例 #5
0
 public ServiceDependency Service(ContainerService service, object value, string name = null)
 {
     return SetName(new ServiceDependency
     {
         Status = ServiceStatus.Ok,
         Value = value,
         ContainerService = service
     }, null, name);
 }
コード例 #6
0
		public bool TryGet(out ContainerService result)
		{
			if (value != null)
			{
				result = value;
				return true;
			}
			result = null;
			return false;
		}
コード例 #7
0
 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));
 }
コード例 #8
0
 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);
 }
コード例 #9
0
 public bool TryGet(out ContainerService result)
 {
     if (value != null)
     {
         result = value;
         return(true);
     }
     result = null;
     return(false);
 }
コード例 #10
0
 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;
 }
コード例 #11
0
		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;
		}
コード例 #12
0
        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);
        }
コード例 #13
0
		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;
		}
コード例 #14
0
            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);
                        }
                    }
                }
            }
コード例 #15
0
        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);
        }
コード例 #16
0
 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;
                 }
             }
     }
 }
コード例 #17
0
        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;
                    }
            }
        }
コード例 #18
0
 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);
         }
     }
 }
コード例 #19
0
 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();
 }
コード例 #20
0
 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);
 }
コード例 #21
0
 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);
     }
 }
コード例 #22
0
        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");
            }
        }
コード例 #23
0
 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);
 }
コード例 #24
0
 public void Reuse(ContainerService containerService)
 {
     target = containerService;
     built  = true;
 }
コード例 #25
0
		public void ReleaseInstantiateLock(ContainerService result)
		{
			value = result;
			Monitor.Exit(lockObject);
		}
コード例 #26
0
 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);
 }
コード例 #27
0
 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);
 }
コード例 #28
0
 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);
 }
コード例 #29
0
 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);
 }
コード例 #30
0
 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;
 }
コード例 #31
0
 public void ReleaseInstantiateLock(ContainerService result)
 {
     value = result;
     Monitor.Exit(lockObject);
 }
コード例 #32
0
 public void Reuse(ContainerService containerService)
 {
     target = containerService;
     reused = true;
 }
コード例 #33
0
 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;
                 }
             }
 }
コード例 #34
0
 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);
 }
コード例 #35
0
 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);
 }
コード例 #36
0
        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;
        }
コード例 #37
0
 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);
 }
コード例 #38
0
        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);
        }
コード例 #39
0
 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);
     }
 }