コード例 #1
0
        public override IEnumerable <Expression> Express(ref PipelineBuilder builder)
        {
            var expressions = builder.Express();

            if (null != builder.SeedExpression)
            {
                return(expressions);
            }

            // Select ConstructorInfo
            var selector  = GetOrDefault(builder.Policies);
            var selection = selector.Invoke(builder.Type, builder.InjectionMembers)
                            .FirstOrDefault();

            // Select constructor for the Type
            ConstructorInfo info;

            object[]? resolvers = null;

            switch (selection)
            {
            case ConstructorInfo memberInfo:
                info = memberInfo;
                break;

            case MethodBase <ConstructorInfo> injectionMember:
                info      = injectionMember.MemberInfo(builder.Type);
                resolvers = injectionMember.Data;
                break;

            case Exception exception:
                return(new[] {
                    Expression.IfThen(NullEqualExisting, Expression.Throw(Expression.Constant(exception)))
                }.Concat(expressions));

            default:
                return(NoConstructorExpr.Concat(expressions));
            }

            return(new[] { GetResolverExpression(info, resolvers, builder.LifetimeManager is PerResolveLifetimeManager) }.Concat(expressions));
        }
コード例 #2
0
        public override ResolveDelegate <BuilderContext>?Build(ref PipelineBuilder builder)
        {
            // Pipeline
            var type     = builder.Type;
            var name     = builder.Name;
            var pipeline = builder.Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));

            return((ref BuilderContext context) =>
            {
                try
                {
                    // Build the type
                    return pipeline(ref context);
                }
                catch (Exception ex) when(ex.InnerException is InvalidRegistrationException &&
                                          null == context.DeclaringType)
                {
                    throw new ResolutionFailedException(context.Type, context.Name,
                                                        $"Resolution failed with error: {ex.Message}\n\nFor more detailed information run Unity in debug mode: new UnityContainer(enableDiagnostic: true)", ex);
                }
            });
        }
コード例 #3
0
ファイル: SetupDiagnostic.cs プロジェクト: elkadeem/container
        public override ResolveDelegate <BuilderContext>?Build(ref PipelineBuilder builder)
        {
            // Pipeline
            var type     = builder.Type;
            var name     = builder.Name;
            var pipeline = builder.Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));

            return((ref BuilderContext context) =>
            {
#if !NET40
                // Check call stack for cyclic references
                var value = GetPerResolveValue(context.Parent, context.Type, context.Name);
                if (LifetimeManager.NoValue != value)
                {
                    return value;
                }
#endif
                try
                {
                    // Build the type
                    return pipeline(ref context);
                }
                catch (Exception ex)
                {
                    ex.Data.Add(Guid.NewGuid(), null == context.Name
                        ? (object)context.Type
                        : new Tuple <Type, string?>(context.Type, context.Name));

                    if (null != context.DeclaringType)
                    {
                        throw;
                    }

                    var message = CreateMessage(ex);
                    throw new ResolutionFailedException(context.Type, context.Name, message, ex);
                }
            });
        }
コード例 #4
0
        public override IEnumerable <Expression> Express(ref PipelineBuilder builder)
        {
            var expressions = builder.Express();

            var infoExpr = Expression.Condition(
                Expression.Equal(Expression.Constant(null), PipelineContextExpression.Name),
                Expression.Convert(PipelineContextExpression.Type, typeof(object)),
                Expression.Convert(Expression.New(TupleConstructor, PipelineContextExpression.Type, PipelineContextExpression.Name), typeof(object)));

            var filter = Expression.OrElse(
                Expression.TypeIs(ExceptionExpr, typeof(InvalidRegistrationException)),
                Expression.TypeIs(ExceptionExpr, typeof(CircularDependencyException)));

            var tryBody   = Expression.Block(expressions);
            var catchBody = Expression.Block(tryBody.Type,
                                             Expression.IfThen(filter, Expression.Call(ExceptionDataExpr, AddMethodInfo, Expression.Convert(CallNewGuidExpr, typeof(object)), infoExpr)),
                                             Expression.Rethrow(tryBody.Type));

            return(new Expression[]
            {
                Expression.Call(ValidateMethod, PipelineContextExpression.Parent, PipelineContextExpression.Type, PipelineContextExpression.Name),
                Expression.TryCatch(tryBody, Expression.Catch(ExceptionExpr, catchBody))
            });
        }
コード例 #5
0
        public override ResolveDelegate <PipelineContext>?Build(ref PipelineBuilder builder)
        {
            // Skip if already have a resolver
            if (null != builder.SeedMethod)
            {
                return(builder.Pipeline());
            }

            // Try to get resolver
            Type?generic  = null;
            var  resolver = builder.Policies?.Get(typeof(ResolveDelegate <PipelineContext>)) ??
                            builder.ContainerContext.Get(builder.Type, typeof(ResolveDelegate <PipelineContext>));

            if (null == resolver)
            {
#if NETCOREAPP1_0 || NETSTANDARD1_0
                if (null != builder.Type && builder.Type.GetTypeInfo().IsGenericType)
#else
                if (null != builder.Type && builder.Type.IsGenericType)
#endif
                {
                    generic  = builder.Type.GetGenericTypeDefinition();
                    resolver = builder.ContainerContext.Get(generic, typeof(ResolveDelegate <PipelineContext>));
                }
            }

            // Process if found
            if (null != resolver)
            {
                return(builder.Pipeline((ResolveDelegate <PipelineContext>)resolver));
            }

            // Try finding factory
            TypeFactoryDelegate?factory = builder.Policies?.Get <TypeFactoryDelegate>();

#if NETCOREAPP1_0 || NETSTANDARD1_0
            if (null != builder.Type && builder.Type.GetTypeInfo().IsGenericType)
#else
            if (null != builder.Type && builder.Type.IsGenericType)
#endif
            {
                factory = (TypeFactoryDelegate?)builder.ContainerContext.Get(builder.Type.GetGenericTypeDefinition(),
                                                                             typeof(TypeFactoryDelegate));
            }
            else if (null != builder.Type && builder.Type.IsArray)
            {
                if (builder.Type.GetArrayRank() == 1)
                {
                    var resolve = ArrayResolver.Factory(builder.Type, builder.ContainerContext.Container);
                    return(builder.Pipeline((ref PipelineContext context) => resolve(ref context)));
                }
                else
                {
                    var message = $"Invalid array {builder.Type}. Only arrays of rank 1 are supported";
                    return((ref PipelineContext context) => throw new InvalidRegistrationException(message));
                }
            }

            Debug.Assert(null != builder.Type);

            return(null != factory
                ? builder.Pipeline(factory(builder.Type, builder.ContainerContext.Container))
                : builder.Pipeline());
        }
コード例 #6
0
        public override ResolveDelegate <BuilderContext>?Build(ref PipelineBuilder builder)
        {
            var lifetime     = builder.Registration.LifetimeManager;
            var pipeline     = builder.Pipeline();
            var parent       = IntPtr.Zero;
            var type         = builder.Type;
            var registration = builder.Registration;


            // No Lifetime Manager
            if (null == lifetime || lifetime is TransientLifetimeManager)
            {
                return((ref BuilderContext context) =>
                {
                    // In Sync mode just execute pipeline
                    if (!context.Async)
                    {
                        return pipeline(ref context);
                    }

                    // Async mode
                    var list = context.List;
                    var unity = context.ContainerContext;
                    var overrides = context.Overrides;
#if !NET40
                    unsafe
                    {
                        var thisContext = this;
                        parent = new IntPtr(Unsafe.AsPointer(ref thisContext));
                    }
#endif
                    // Create and return a task that creates an object
                    return Task.Factory.StartNew(() =>
                    {
                        var c = new BuilderContext
                        {
                            List = list,
                            Type = type,
                            ContainerContext = unity,
                            Registration = registration,
                            Overrides = overrides,
                            DeclaringType = type,
                            Parent = parent,
                        };

                        // Execute pipeline
                        return pipeline(ref c);
                    });
                });
            }


            // Per Resolve Lifetime Manager
            if (lifetime is PerResolveLifetimeManager)
            {
                return (ref BuilderContext context) =>
                       {
                           object value;

                           // Get it from context
                           var policy = (LifetimeManager?)context.Get(typeof(LifetimeManager));

                           // Return if holds value
                           if (null != policy)
                           {
                               value = policy.GetValue(context.ContainerContext.Lifetime);
                               if (LifetimeManager.NoValue != value)
                               {
                                   return value;
                               }
                           }

                           // Compose down the chain
                           value = pipeline(ref context);
                           policy?.SetValue(value, context.ContainerContext.Lifetime);

                           return value;
                       }
            }
            ;


            // Requires Recovery during resolution
            if (lifetime is SynchronizedLifetimeManager recoverableManager)
            {
                return((ref BuilderContext context) =>
                {
                    try
                    {
                        // Return if holds value
                        var value = lifetime.GetValue(context.ContainerContext.Lifetime);
                        if (LifetimeManager.NoValue != value)
                        {
                            return value;
                        }

                        // Compose
                        value = pipeline(ref context);

                        // Set value
                        lifetime.SetValue(value, context.ContainerContext.Lifetime);
                        return value;
                    }
                    catch when(null != recoverableManager)
                    {
                        recoverableManager.Recover();
                        throw;
                    }
                });
            }

            return((ref BuilderContext context) =>
            {
                // Return if holds value
                var value = lifetime.GetValue(context.ContainerContext.Lifetime);
                if (LifetimeManager.NoValue != value)
                {
                    return value;
                }

                // Compose down the chain
                value = pipeline(ref context);
                lifetime.SetValue(value, context.ContainerContext.Lifetime);

                return value;
            });
        }

        #endregion
    }
コード例 #7
0
        public override ResolveDelegate <BuilderContext>?Build(ref PipelineBuilder builder)
        {
            if (null != builder.Seed)
            {
                return(builder.Pipeline());
            }

            var type = builder.Type;

#if NETSTANDARD1_0 || NETCOREAPP1_0
            var typeInfo = type.GetTypeInfo();
#else
            var typeInfo = type;
#endif
            // Validate if Type could be created
            if (typeInfo.IsInterface)
            {
                var pipeline = builder.Pipeline();
                return((ref BuilderContext context) =>
                {
                    if (null == context.Existing)
                    {
                        throw new InvalidRegistrationException(string.Format(CannotConstructInterface, context.Type));
                    }

                    return null == pipeline ? context.Existing : pipeline.Invoke(ref context);
                });
            }

            if (typeInfo.IsAbstract)
            {
                var pipeline = builder.Pipeline();
                return((ref BuilderContext context) =>
                {
                    if (null == context.Existing)
                    {
                        throw new InvalidRegistrationException(string.Format(CannotConstructAbstractClass, context.Type));
                    }

                    return null == pipeline ? context.Existing : pipeline.Invoke(ref context);
                });
            }

            if (typeInfo.IsSubclassOf(typeof(Delegate)))
            {
                var pipeline = builder.Pipeline();
                return((ref BuilderContext context) =>
                {
                    if (null == context.Existing)
                    {
                        throw new InvalidRegistrationException(string.Format(CannotConstructDelegate, context.Type));
                    }

                    return null == pipeline ? context.Existing : pipeline.Invoke(ref context);
                });
            }

            if (type == typeof(string))
            {
                var pipeline = builder.Pipeline();
                return((ref BuilderContext context) =>
                {
                    if (null == context.Existing)
                    {
                        throw new InvalidRegistrationException(string.Format(TypeIsNotConstructable, context.Type));
                    }

                    return null == pipeline ? context.Existing : pipeline.Invoke(ref context);
                });
            }

            return(base.Build(ref builder));
        }
コード例 #8
0
        public override ResolveDelegate <BuilderContext>?Build(ref PipelineBuilder builder)
        {
            var pipeline = builder.Pipeline();

            if (null != builder.Seed)
            {
                return(pipeline);
            }

            // Verify if can build
#if NETSTANDARD1_0 || NETCOREAPP1_0
            if (builder.Type.GetTypeInfo().IsGenericTypeDefinition)
#else
            if (builder.Type.IsGenericTypeDefinition)
#endif
            {
                return((ref BuilderContext context) =>
                {
                    if (null == context.Existing)
                    {
                        throw new InvalidOperationException(
                            $"The type {context.Type} is an open generic. An open generic type cannot be created.",
                            new InvalidRegistrationException());
                    }

                    return null == pipeline ? context.Existing : pipeline.Invoke(ref context);
                });
            }

            // Select ConstructorInfo
            var selector  = GetOrDefault(builder.Registration);
            var selection = selector.Invoke(builder.Type, builder.Registration)
                            .FirstOrDefault();

            // Select constructor for the Type
            ConstructorInfo info;
            object[]? resolvers = null;

            switch (selection)
            {
            case ConstructorInfo memberInfo:
                info = memberInfo;
                break;

            case MethodBase <ConstructorInfo> injectionMember:
                info      = injectionMember.MemberInfo(builder.Type);
                resolvers = injectionMember.Data;
                break;

            case Exception exception:
                return((ref BuilderContext c) =>
                {
                    if (null == c.Existing)
                    {
                        throw exception;
                    }

                    return null == pipeline ? c.Existing : pipeline.Invoke(ref c);
                });

            default:
                return((ref BuilderContext c) =>
                {
                    if (null == c.Existing)
                    {
                        throw new InvalidOperationException($"No public constructor is available for type {c.Type}.",
                                                            new InvalidRegistrationException());
                    }

                    return null == pipeline ? c.Existing : pipeline.Invoke(ref c);
                });
            }

            var lifetimeManager = (LifetimeManager?)builder.Registration.Get(typeof(LifetimeManager));

            return(lifetimeManager is PerResolveLifetimeManager
                ? GetPerResolveDelegate(info, resolvers, pipeline)
                : GetResolverDelegate(info, resolvers, pipeline));
        }
コード例 #9
0
 public virtual IEnumerable <Expression> Express(ref PipelineBuilder builder) => builder.Express();
コード例 #10
0
 public virtual ResolveDelegate <PipelineContext>?Build(ref PipelineBuilder builder) => builder.Pipeline();
コード例 #11
0
        /// <inheritdoc />
        Task IUnityContainerAsync.RegisterFactory(IEnumerable <Type>?interfaces, string?name, Func <IUnityContainer, Type, string?, object?> factory, IFactoryLifetimeManager?lifetimeManager)
        {
            // Validate input
            if (null == interfaces)
            {
                throw new ArgumentNullException(nameof(interfaces));
            }
            if (null == factory)
            {
                throw new ArgumentNullException(nameof(factory));
            }

            return(Task.Factory.StartNew(() =>
            {
                // TODO: implementation required
                var type = interfaces.First();

                // Lifetime Manager
                var manager = lifetimeManager as LifetimeManager ?? Context.FactoryLifetimeManager.CreateLifetimePolicy();
                if (manager.InUse)
                {
                    throw new InvalidOperationException(LifetimeManagerInUse);
                }
                manager.InUse = true;

                // Target Container
                var container = manager is SingletonLifetimeManager ? _root : this;
                Debug.Assert(null != container);

                // If Disposable add to container's lifetime
                if (manager is IDisposable managerDisposable)
                {
                    container.LifetimeContainer.Add(managerDisposable);
                }

                // Create registration
                var registration = new ExplicitRegistration(container, name, type, manager);

                // Factory resolver
                var resolver = lifetimeManager is PerResolveLifetimeManager
                    ? (ResolveDelegate <BuilderContext>)((ref BuilderContext c) =>
                {
                    c.Existing = factory(c.Container, c.Type, c.Name);
                    c.Set(typeof(LifetimeManager), new InternalPerResolveLifetimeManager(c.Existing));
                    return c.Existing;
                })
                    : ((ref BuilderContext c) => factory(c.Container, c.Type, c.Name));
                registration.Set(typeof(ResolveDelegate <BuilderContext>), resolver);

                // Build Pipeline
                PipelineBuilder builder = new PipelineBuilder(registration, container, Context.FactoryPipelineCache);
                registration.Pipeline = builder.Pipeline();

                // Register
                var previous = container.Register(type, name, registration);

                // Allow reference adjustment and disposal
                if (null != previous && 0 == previous.Release() &&
                    previous.LifetimeManager is IDisposable disposable)
                {
                    // Dispose replaced lifetime manager
                    container.LifetimeContainer.Remove(disposable);
                    disposable.Dispose();
                }

                // TODO: Raise event
                // container.Registering?.Invoke(this, new RegisterEventArgs(type, type, name, manager));
            }));
        }