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)); }
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); } }); }
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); } }); }
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)) }); }
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()); }
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 }
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)); }
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)); }
public virtual IEnumerable <Expression> Express(ref PipelineBuilder builder) => builder.Express();
public virtual ResolveDelegate <PipelineContext>?Build(ref PipelineBuilder builder) => builder.Pipeline();
/// <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)); })); }