예제 #1
0
            public void CreateInstanceBy(CallTarget callTarget, bool owned)
            {
                object instance;

                try
                {
                    instance = callTarget.method == null
                                                ? callTarget.factory(this)
                                                : callTarget.method.Compile()(callTarget.self, callTarget.actualArguments);
                }
                catch (ServiceCouldNotBeCreatedException e)
                {
                    if (!string.IsNullOrEmpty(e.Message))
                    {
                        SetComment(e.Message);
                    }
                    return;
                }
                catch (SimpleContainerException e)
                {
                    if (Status == ServiceStatus.Ok)
                    {
                        SetError(e);
                    }
                    return;
                }
                catch (Exception e)
                {
                    SetError(e);
                    return;
                }
                AddInstance(instance, owned, false);
            }
        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);
            }
        }
예제 #3
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);
        }
        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));
        }
        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);
            }
        }