Ejemplo n.º 1
0
        private object GetInstance(Type type, bool throwError)
        {
            var scope    = IoCScope.GetCurrent();
            var hasScope = scope != null;

            if (hasScope && scope.TryGetInstance(type, out object instance))
            {
                return(instance);
            }

            var hasRegistration = _registrator.TryGet(type, out IIoCRegistration registration);

            if (hasRegistration && registration.MustBeScoped && !hasScope)
            {
                if (throwError)
                {
                    throw new InvalidOperationException($"The type {type.FullName} could not be created since it requires a scope");
                }
                else
                {
                    return(null);
                }
            }

            var newInstance = _factory.GetInstance(type, throwError);

            if (newInstance == null)
            {
                return(null);
            }
            if (hasScope)
            {
                if (hasRegistration)
                {
                    if (!registration.CanBeScoped)
                    {
                        return(newInstance);
                    }
                    scope.Register(registration, newInstance);
                }
                else
                {
                    scope.Register(newInstance);
                }
            }
            return(newInstance);
        }
Ejemplo n.º 2
0
        public IInstanceFactory GetFactory(Type type, bool throwError)
        {
            if (_typeFactories.TryGetValue(type, out IInstanceFactory factory))
            {
                return(factory);
            }

            if (_registrator.TryGet(type, out IIoCRegistration registration))
            {
                if (registration.HasInstanceGetter)
                {
                    if (type == registration.Type)
                    {
                        _typeFactories.Add(type, registration);
                        return(registration);
                    }
                    factory = (IInstanceFactory)Activator.CreateInstance(typeof(DelegatedInstanceProvider <>).MakeGenericType(type), registration);
                    _typeFactories.Add(type, factory);
                    return(factory);
                }
                else if (type != registration.Type)
                {
                    factory = GetFactory(registration.Type, throwError);
                    if (factory != null)
                    {
                        factory = (IInstanceFactory)Activator.CreateInstance(typeof(DelegatedInstanceProvider <>).MakeGenericType(type), factory);
                        _typeFactories.Add(type, factory);
                    }
                    return(factory);
                }
            }

            var info         = type.GetTypeInfo();
            var constructors = info.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            if (constructors.Length > 1)
            {
                constructors = constructors.Where(c => c.IsPublic).ToArray();
            }

            if (constructors.Length != 1)
            {
                if (throwError)
                {
                    throw IoCFactoryException.AmbigiousConstructor(type);
                }
                else
                {
                    return(null);
                }
            }

            var constructor = constructors[0];

            var parameters  = constructor.GetParameters();
            var paramLength = parameters.Length;

            var properties = info.GetProperties(BindingFlags.Instance | BindingFlags.Public)
                             .Where(p => p.CanWrite && _registrator.Contains(p.PropertyType))
                             .ToArray();

            paramLength += properties.Length;

            var factoryParams = new object[paramLength > 0 ? paramLength + 2 : 1];
            var factoryTypes  = new Type[paramLength + 1];

            factoryTypes[0]  = type;
            factoryParams[0] = constructor;

            if (paramLength > 0)
            {
                factoryParams[1] = properties;
            }

            for (var i = 0; i < parameters.Length; i++)
            {
                var parameter    = parameters[i];
                var paramFactory = GetFactory(parameter.ParameterType, throwError);
                if (paramFactory == null)
                {
                    return(null);
                }
                factoryParams[i + 2] = paramFactory;
                factoryTypes[i + 1]  = parameter.ParameterType;
            }

            if (properties.Length > 0)
            {
                var paramIndex = parameters.Length + 1;
                for (var i = 0; i < properties.Length; i++)
                {
                    var propertyType = properties[i].PropertyType;
                    factoryParams[paramIndex + 1] = GetFactory(propertyType, throwError);
                    factoryTypes[paramIndex++]    = propertyType;
                }
            }

            var factoryType        = GetFactoryType(factoryTypes, out bool useDynamic);
            var factoryConstructor = factoryType.GetTypeInfo().GetConstructors()[0];

            if (useDynamic)
            {
                factory = (IInstanceFactory)factoryConstructor.Invoke(new object[] {
                    constructor,
                    properties,
                    _provider,
                    factoryParams.OfType <IInstanceFactory>().ToArray()
                });
            }
            else
            {
                factory = (IInstanceFactory)factoryConstructor.Invoke(factoryParams);
            }
            _typeFactories.Add(type, factory);

            return(factory);
        }