Пример #1
0
        private InstanceFactoryBuilderDelegate ExistingInstanceRawFactoryBuilder(
            InstanceFactoryBuilderDelegate next)
        {
            return(factoryConfig =>
            {
                TypeInfo configTypeInfo = factoryConfig.GetType().GetTypeInfo();

                if (configTypeInfo.IsGenericType &&
                    (configTypeInfo.GetGenericTypeDefinition() == typeof(IxExistingInstanceFactoryConfig <>)))
                {
                    object instanceObj = configTypeInfo.GetDeclaredProperty("Instance").GetValue(factoryConfig);
                    if (instanceObj == null)
                    {
                        throw new InvalidOperationException(
                            "Existing instance factory config should have not null instance.");
                    }

                    return new IxInstanceFactory(
                        async(instance, parentInstance, resolveContext, frame) => instanceObj,
                        configTypeInfo.GenericTypeArguments[0]);
                }

                return next(factoryConfig);
            });
        }
Пример #2
0
        private InstanceFactoryBuilderDelegate ClassInstanceFactoryBuilder(
            InstanceFactoryBuilderDelegate next)
        {
            return(factoryConfig =>
            {
                TypeInfo configTypeInfo = factoryConfig.GetType().GetTypeInfo();

                if (configTypeInfo.IsGenericType &&
                    (configTypeInfo.GetGenericTypeDefinition() == typeof(IxClassInstanceBuilderConfig <>)))
                {
                    TypeInfo instanceClass = configTypeInfo.GenericTypeArguments[0].GetTypeInfo();
                    ConstructorInfo[] constructors =
                        instanceClass.DeclaredConstructors.Where(x => !x.IsStatic).ToArray();
                    if (constructors.Length == 0)
                    {
                        // Currently impossible case.
                        throw new IxConfigurationException(
                            $"Cannot use IxClassInstanceFactory because no any constructors found in the class {instanceClass.FullName}.");
                    }

                    if (constructors.Length > 1)
                    {
                        throw new IxConfigurationException(
                            $"Cannot use IxClassInstanceFactory because more than one constructors defined in the class {instanceClass.FullName}.");
                    }

                    ConstructorInfo constructorInfo = constructors.Single();

                    HashSet <IxIdentifier> dependencies =
                        constructorInfo.GetParameters().Select(x => new IxIdentifier(x.ParameterType)).ToHashSet();
                    if (dependencies.Count != constructorInfo.GetParameters().Length)
                    {
                        throw new IxConfigurationException(
                            "Multiple parameters with the same type not supported by IxClassRawFactory.");
                    }

                    // TODO: Add tests for this feature
                    List <RequireAttribute> requireAttributes =
                        constructorInfo.GetCustomAttributes <RequireAttribute>().ToList();
                    foreach (RequireAttribute requireAttribute in requireAttributes)
                    {
                        if (!dependencies.Add(new IxIdentifier(requireAttribute.Type)))
                        {
                            throw new IxConfigurationException(
                                "Multiple parameters with the same type not supported by IxClassRawFactory.");
                        }
                    }

                    // instance argument here is half-instantiated instance.
                    return new IxInstanceFactory(
                        (instance, parentInstance, resolveContext, frame) => ResolveList(
                            instance,
                            dependencies,
                            resolveContext,
                            frame,
                            async resolvedDependencies =>
                    {
                        try
                        {
                            object[] arguments = constructorInfo.GetParameters()
                                                 .Select(
                                x =>
                                resolvedDependencies[new IxIdentifier(x.ParameterType)]
                                .Object)
                                                 .ToArray();

                            object instanceObj = constructorInfo.Invoke(arguments);

                            Critical.Assert(
                                instanceObj != null,
                                "Constructor call through reflection should not return null.");

                            lock (instance.ProviderNode.Host.InstanceTreeSyncRoot)
                            {
                                foreach (KeyValuePair <IxIdentifier, IIxInstance> kvp
                                         in resolvedDependencies)
                                {
                                    // ReSharper disable once ObjectCreationAsStatement
                                    new IxReferenceLock(kvp.Value, instance);
                                }
                            }

                            // Just to avoid multiple functions.
                            return instanceObj;
                        }
                        catch (TargetInvocationException ex)
                        {
                            throw ex.InnerException;
                        }
                    }),
                        configTypeInfo.GenericTypeArguments[0]);
                }

                return next(factoryConfig);
            });
        }
Пример #3
0
        private InstanceFactoryBuilderDelegate DelegateInstanceBuilder(
            InstanceFactoryBuilderDelegate next)
        {
            return(instanceBuilderConfig =>
            {
                TypeInfo configTypeInfo = instanceBuilderConfig.GetType().GetTypeInfo();

                var delegateInstanceBuilderConfig = instanceBuilderConfig as IxDelegateInstanceBuilderConfig;
                if (delegateInstanceBuilderConfig == null)
                {
                    return next(instanceBuilderConfig);
                }

                TypeInfo delegateType = delegateInstanceBuilderConfig.Func.GetType().GetTypeInfo();

                MethodInfo methodInfo = delegateType.GetDeclaredMethod("Invoke");

                HashSet <IxIdentifier> dependencies =
                    methodInfo.GetParameters().Select(x => new IxIdentifier(x.ParameterType)).ToHashSet();
                if (dependencies.Count != methodInfo.GetParameters().Length)
                {
                    throw new IxConfigurationException(
                        "Multiple parameters with the same type not supported by IxClassRawFactory.");
                }

                // TODO: Add tests for this feature
                List <RequireAttribute> requireAttributes =
                    methodInfo.GetCustomAttributes <RequireAttribute>().ToList();
                foreach (RequireAttribute requireAttribute in requireAttributes)
                {
                    if (!dependencies.Add(new IxIdentifier(requireAttribute.Type)))
                    {
                        throw new IxConfigurationException(
                            "Multiple parameters with the same type not supported by IxClassRawFactory.");
                    }
                }

                return new IxInstanceFactory(
                    (instance, parentInstance, resolveContext, frame) => ResolveList(
                        instance,
                        dependencies,
                        resolveContext,
                        frame,
                        async resolvedDependencies =>
                {
                    object[] arguments = methodInfo.GetParameters()
                                         .Select(
                        x =>
                        resolvedDependencies[new IxIdentifier(x.ParameterType)].Object)
                                         .ToArray();

                    object instanceObjTask;
                    Task instanceObjTaskCasted;
                    try
                    {
                        // TODO: Optimize me.
                        instanceObjTask = methodInfo.Invoke(
                            delegateInstanceBuilderConfig.Func,
                            arguments);
                        instanceObjTaskCasted = (Task)instanceObjTask.GetType().GetTypeInfo()
                                                .GetDeclaredMethod("AsTask")
                                                .Invoke(instanceObjTask, new object[] { });
                        await instanceObjTaskCasted;
                    }
                    catch (TargetInvocationException ex)
                    {
                        throw ex.InnerException;
                    }

                    object instanceObj = instanceObjTaskCasted.GetResult();

                    // TODO: TryCast,
                    // TODO: Allow null result.
                    Critical.Assert(
                        instanceObj != null,
                        "Constructor call through reflection should not return null.");

                    lock (instance.ProviderNode.Host.InstanceTreeSyncRoot)
                    {
                        foreach (KeyValuePair <IxIdentifier, IIxInstance> kvp
                                 in resolvedDependencies)
                        {
                            // ReSharper disable once ObjectCreationAsStatement
                            new IxReferenceLock(kvp.Value, instance);
                        }
                    }

                    return instanceObj;
                }),
                    methodInfo.ReturnType.GenericTypeArguments[0]);
            });
        }