public override IEnumerable <ExportDescriptorPromise> GetExportDescriptors(
            CompositionContract contract, DependencyAccessor descriptorAccessor)
        {
            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug($"Getting Export Descriptors:"
                                 + $" contractName=[{contract.ContractName}]"
                                 + $" contractType=[{contract.ContractType.FullName}]");
            }

            var svc = _serviceProvider.GetService(contract.ContractType);

            if (svc == null)
            {
                if (_logger.IsEnabled(LogLevel.Debug))
                {
                    _logger.LogDebug($"No DI service found for"
                                     + $" contractType=[{contract.ContractType.FullName}]");
                }
                yield break;
            }

            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug($"Resolved DI service for"
                                 + $" contractType=[{contract.ContractType.FullName}]"
                                 + $" service=[{svc}]");
            }

            CompositeActivator ca = (ctx, op) => svc;

            yield return(new ExportDescriptorPromise(contract, ORIGIN_NAME, true,
                                                     NoDependencies, deps => ExportDescriptor.Create(ca, NoMetadata)));
        }
예제 #2
0
        public override CompositeActivator RewriteActivator(
            TypeInfo partType,
            CompositeActivator activatorBody,
            IDictionary<string, object> partMetadata,
            IEnumerable<CompositionDependency> dependencies)
        {
            if (!ContractHelpers.IsShared(partMetadata))
                return activatorBody;

            object sharingBoundaryMetadata;
            if (!partMetadata.TryGetValue(SharingBoundaryPartMetadataName, out sharingBoundaryMetadata))
                sharingBoundaryMetadata = null;

            var sharingBoundary = (string)sharingBoundaryMetadata;
            var sharingKey = LifetimeContext.AllocateSharingId();

            return (c, o) =>
            {
                var scope = c.FindContextWithin(sharingBoundary);
                if (object.ReferenceEquals(scope, c))
                    return scope.GetOrCreate(sharingKey, o, activatorBody);
                else
                    return CompositionOperation.Run(scope, (c1, o1) => c1.GetOrCreate(sharingKey, o1, activatorBody));
            };
        }
예제 #3
0
        public override CompositeActivator RewriteActivator(
            TypeInfo partType,
            CompositeActivator activatorBody,
            IDictionary <string, object> partMetadata,
            IEnumerable <CompositionDependency> dependencies)
        {
            if (!ContractHelpers.IsShared(partMetadata))
            {
                return(activatorBody);
            }

            object sharingBoundaryMetadata;

            if (!partMetadata.TryGetValue(SharingBoundaryPartMetadataName, out sharingBoundaryMetadata))
            {
                sharingBoundaryMetadata = null;
            }

            var sharingBoundary = (string)sharingBoundaryMetadata;
            var sharingKey      = LifetimeContext.AllocateSharingId();

            return((c, o) =>
            {
                var scope = c.FindContextWithin(sharingBoundary);
                if (object.ReferenceEquals(scope, c))
                {
                    return scope.GetOrCreate(sharingKey, o, activatorBody);
                }
                else
                {
                    return CompositionOperation.Run(scope, (c1, o1) => c1.GetOrCreate(sharingKey, o1, activatorBody));
                }
            });
        }
예제 #4
0
        public void Create_Valid_ReturnsExpected(CompositeActivator activator, Dictionary <string, object> metadata)
        {
            ExportDescriptor descriptor = ExportDescriptor.Create(activator, metadata);

            Assert.Same(activator, descriptor.Activator);
            Assert.Same(metadata, descriptor.Metadata);
        }
예제 #5
0
        public DirectExportDescriptor(CompositeActivator activator, IDictionary<string, object> metadata)
        {
            Requires.NotNull(activator, "activator");
            Requires.NotNull(metadata, "metadata");

            _activator = activator;
            _metadata = metadata;
        }
예제 #6
0
        public DirectExportDescriptor(CompositeActivator activator, IDictionary <string, object> metadata)
        {
            Requires.NotNull(activator, "activator");
            Requires.NotNull(metadata, "metadata");

            _activator = activator;
            _metadata  = metadata;
        }
예제 #7
0
        CompositeActivator CreateActivator(IEnumerable <CompositionDependency> dependencies)
        {
            var dependenciesByImport = dependencies.GroupBy(d => (ContractBasedImportDefinition)d.Site, d => d.Target.GetDescriptor());
            var prereqs    = dependenciesByImport.Where(d => d.Key.IsPrerequisite).ToArray();
            var nonprereqs = dependenciesByImport.Where(d => !d.Key.IsPrerequisite).ToArray();
            var unset      = _part.ImportDefinitions.Where(id => !prereqs.Concat(nonprereqs).Any(k => k.Key.Equals((ContractBasedImportDefinition)id))).ToArray();

            CompositeActivator construct = (c, o) =>
            {
                var result = _part.CreatePart();
                if (result is IDisposable)
                {
                    c.AddBoundInstance((IDisposable)result);
                }

                foreach (var pre in prereqs)
                {
                    result.SetImport(pre.Key, DependenciesToExports(c, pre));
                }

                foreach (var un in unset)
                {
                    result.SetImport(un, Enumerable.Empty <Export>());
                }

                o.AddNonPrerequisiteAction(() =>
                {
                    foreach (var np in nonprereqs)
                    {
                        result.SetImport(np.Key, DependenciesToExports(c, np));
                    }
                });

                o.AddPostCompositionAction(() =>
                {
                    result.Activate();
                });

                return(result);
            };

            if (!IsShared)
            {
                return(construct);
            }

            var sharingId = LifetimeContext.AllocateSharingId();
            CompositeActivator constructAndShare = (c, o) => c.GetOrCreate(sharingId, o, construct);

            return((c, o) =>
            {
                var scope = c.FindContextWithin(_boundary);
                return scope.Equals(c) ?
                constructAndShare(scope, o) :
                CompositionOperation.Run(scope, constructAndShare);
            });
        }
예제 #8
0
        public CompositeActivator GetActivator(IEnumerable <CompositionDependency> dependencies)
        {
            if (_activator == null)
            {
                _activator = CreateActivator(dependencies);
            }

            return(_activator);
        }
예제 #9
0
        public override CompositeActivator RewriteActivator(
            TypeInfo partType,
            CompositeActivator activator,
            IDictionary <string, object> partMetadata,
            IEnumerable <CompositionDependency> dependencies)
        {
            var propertyDependencies = dependencies
                                       .Where(dep => dep.Site is PropertyImportSite)
                                       .ToDictionary(d => ((PropertyImportSite)d.Site).Property);

            if (propertyDependencies.Count == 0)
            {
                return(activator);
            }

            var lc    = Expression.Parameter(typeof(LifetimeContext));
            var op    = Expression.Parameter(typeof(CompositionOperation));
            var inst  = Expression.Parameter(typeof(object));
            var typed = Expression.Variable(partType.AsType());

            var statements  = new List <Expression>();
            var assignTyped = Expression.Assign(typed, Expression.Convert(inst, partType.AsType()));

            statements.Add(assignTyped);

            foreach (var d in propertyDependencies)
            {
                var property = d.Key;

                var assignment = Expression.Assign(
                    Expression.MakeMemberAccess(typed, property),
                    Expression.Convert(
                        Expression.Call(
                            Expression.Constant(d.Value.Target.GetDescriptor().Activator),
                            ActivatorInvokeMethod,
                            lc,
                            op),
                        property.PropertyType));

                statements.Add(assignment);
            }

            statements.Add(inst);

            var setAll    = Expression.Block(new[] { typed }, statements);
            var setAction = Expression.Lambda <Func <object, LifetimeContext, CompositionOperation, object> >(
                setAll, inst, lc, op).Compile();

            return((c, o) =>
            {
                var i = activator(c, o);
                o.AddNonPrerequisiteAction(() => setAction(i, c, o));
                return i;
            });
        }
예제 #10
0
        /// <summary>
        /// Execute a new composition operation starting within the specified lifetime
        /// context, for the specified activator.
        /// </summary>
        /// <param name="outermostLifetimeContext">Context in which to begin the operation (the operation can flow
        /// to the parents of the context if requried).</param>
        /// <param name="compositionRootActivator">Activator that will drive the operation.</param>
        /// <returns>The composed object graph.</returns>
        public static object Run(LifetimeContext outermostLifetimeContext, CompositeActivator compositionRootActivator)
        {
            Requires.ArgumentNotNull(outermostLifetimeContext, "outermostLifetimeContext");
            Requires.ArgumentNotNull(compositionRootActivator, "compositionRootActivator");

            using (var operation = new CompositionOperation())
            {
                var result = compositionRootActivator(outermostLifetimeContext, operation);
                operation.Complete();
                return(result);
            }
        }
예제 #11
0
        /// <summary>
        /// Execute a new composition operation starting within the specified lifetime
        /// context, for the specified activator.
        /// </summary>
        /// <param name="outermostLifetimeContext">Context in which to begin the operation (the operation can flow
        /// to the parents of the context if requried).</param>
        /// <param name="compositionRootActivator">Activator that will drive the operation.</param>
        /// <returns>The composed object graph.</returns>
        public static object Run(LifetimeContext outermostLifetimeContext, CompositeActivator compositionRootActivator)
        {
            Requires.NotNull(outermostLifetimeContext, nameof(outermostLifetimeContext));
            Requires.NotNull(compositionRootActivator, nameof(compositionRootActivator));

            using (var operation = new CompositionOperation())
            {
                var result = compositionRootActivator(outermostLifetimeContext, operation);
                operation.Complete();
                return result;
            }
        }
예제 #12
0
        protected override ExportDescriptor GetExportDescriptor(CompositeActivator partActivator)
        {
            var args = new[] { Expression.Parameter(typeof(LifetimeContext)), Expression.Parameter(typeof(CompositionOperation)) };

            var activator = Expression.Lambda <CompositeActivator>(
                Expression.Property(
                    Expression.Convert(Expression.Call(Expression.Constant(partActivator), ActivatorInvoke, args), _property.DeclaringType),
                    _property),
                args);

            return(ExportDescriptor.Create(activator.Compile(), Metadata));
        }
예제 #13
0
        protected override ExportDescriptor GetExportDescriptor(CompositeActivator partActivator)
        {
            var args = new[] { Expression.Parameter(typeof(LifetimeContext)), Expression.Parameter(typeof(CompositionOperation)) };

            var activator = Expression.Lambda<CompositeActivator>(
                Expression.Property(
                    Expression.Convert(Expression.Call(Expression.Constant(partActivator), s_activatorInvoke, args), _property.DeclaringType),
                    _property),
                args);

            return ExportDescriptor.Create(activator.Compile(), Metadata);
        }
예제 #14
0
        public override CompositeActivator RewriteActivator(
            TypeInfo partType,
            CompositeActivator activator,
            IDictionary<string, object> partMetadata,
            IEnumerable<CompositionDependency> dependencies)
        {
            var propertyDependencies = dependencies
                .Where(dep => dep.Site is PropertyImportSite)
                .ToDictionary(d => ((PropertyImportSite)d.Site).Property);

            if (propertyDependencies.Count == 0)
                return activator;

            var lc = Expression.Parameter(typeof(LifetimeContext));
            var op = Expression.Parameter(typeof(CompositionOperation));
            var inst = Expression.Parameter(typeof(object));
            var typed = Expression.Variable(partType.AsType());

            var statements = new List<Expression>();
            var assignTyped = Expression.Assign(typed, Expression.Convert(inst, partType.AsType()));
            statements.Add(assignTyped);

            foreach (var d in propertyDependencies)
            {
                var property = d.Key;

                var assignment = Expression.Assign(
                    Expression.MakeMemberAccess(typed, property),
                    Expression.Convert(
                        Expression.Call(
                            Expression.Constant(d.Value.Target.GetDescriptor().Activator),
                            s_activatorInvokeMethod,
                            lc,
                            op),
                        property.PropertyType));

                statements.Add(assignment);
            }

            statements.Add(inst);

            var setAll = Expression.Block(new[] { typed }, statements);
            var setAction = Expression.Lambda<Func<object, LifetimeContext, CompositionOperation, object>>(
                setAll, inst, lc, op).Compile();

            return (c, o) =>
            {
                var i = activator(c, o);
                o.AddNonPrerequisiteAction(() => setAction(i, c, o));
                return i;
            };
        }
 public DirectExportDescriptor(CompositeActivator activator, IDictionary <string, object> metadata)
 {
     if (activator == null)
     {
         throw new ArgumentNullException(nameof(activator));
     }
     if (metadata == null)
     {
         throw new ArgumentNullException(nameof(metadata));
     }
     _activator = activator;
     _metadata  = metadata;
 }
        public DelegateExportDescriptorProvider(Func <object> exportedInstanceFactory, Type contractType, string contractName, IDictionary <string, object> metadata, bool isShared)
            : base(contractType, contractName, metadata)
        {
            if (exportedInstanceFactory == null)
            {
                throw new ArgumentNullException("exportedInstanceFactory");
            }

            // Runs the factory method, validates the result and registers it for disposal if necessary.
            CompositeActivator constructor = (c, o) =>
            {
                var result = exportedInstanceFactory();
                if (result == null)
                {
                    throw new InvalidOperationException("Delegate factory returned null.");
                }

                if (result is IDisposable)
                {
                    c.AddBoundInstance((IDisposable)result);
                }

                return(result);
            };

            if (isShared)
            {
                var sharingId = LifetimeContext.AllocateSharingId();
                _activator = (c, o) =>
                {
                    // Find the root composition scope.
                    var scope = c.FindContextWithin(null);
                    if (scope == c)
                    {
                        // We're already in the root scope, create the instance
                        return(scope.GetOrCreate(sharingId, o, constructor));
                    }
                    else
                    {
                        // Composition is moving up the hierarchy of scopes; run
                        // a new operation in the root scope.
                        return(CompositionOperation.Run(scope, (c1, o1) => c1.GetOrCreate(sharingId, o1, constructor)));
                    }
                };
            }
            else
            {
                _activator = constructor;
            }
        }
예제 #17
0
        public CompositeActivator GetActivator(DependencyAccessor definitionAccessor, IEnumerable <CompositionDependency> dependencies)
        {
            if (_partActivator != null)
            {
                return(_partActivator);
            }

            var contextParam  = Expression.Parameter(typeof(LifetimeContext), "cc");
            var operationParm = Expression.Parameter(typeof(CompositionOperation), "op");

            var cps = _constructor.GetParameters();

            Expression[] paramActivatorCalls = new Expression[cps.Length];

            var partActivatorDependencies = dependencies
                                            .Where(dep => dep.Site is ParameterImportSite)
                                            .ToDictionary(d => ((ParameterImportSite)d.Site).Parameter);

            for (var i = 0; i < cps.Length; ++i)
            {
                var pi = cps[i];
                CompositionDependency dep;

                if (partActivatorDependencies.TryGetValue(pi, out dep))
                {
                    var a = dep.Target.GetDescriptor().Activator;
                    paramActivatorCalls[i] =
                        Expression.Convert(Expression.Call(Expression.Constant(a), s_activatorInvoke, contextParam, operationParm), pi.ParameterType);
                }
                else
                {
                    paramActivatorCalls[i] = Expression.Default(pi.ParameterType);
                }
            }

            Expression body = Expression.Convert(Expression.New(_constructor, paramActivatorCalls), typeof(object));

            var activator = Expression
                            .Lambda <CompositeActivator>(body, contextParam, operationParm)
                            .Compile();

            foreach (var activationFeature in _activationFeatures)
            {
                activator = activationFeature.RewriteActivator(_partType, activator, _partMetadata.Value, dependencies);
            }

            _partActivator = activator;
            return(_partActivator);
        }
예제 #18
0
        public override CompositeActivator RewriteActivator(
            TypeInfo partType,
            CompositeActivator activator,
            IDictionary<string, object> partMetadata,
            IEnumerable<CompositionDependency> dependencies)
        {
            if (!typeof(IDisposable).GetTypeInfo().IsAssignableFrom(partType))
                return activator;

            return (c, o) =>
            {
                var inst = (IDisposable)activator(c, o);
                c.AddBoundInstance(inst);
                return inst;
            };
        }
예제 #19
0
        public ExportDescriptorPromise GetPromise(CompositionContract contract, DependencyAccessor descriptorAccessor)
        {
            var origin = _export.ToString();

            if (_export is ICompositionElement)
            {
                origin = ((ICompositionElement)_export).DisplayName;
            }

            return(new ExportDescriptorPromise(contract, origin, _part.IsShared, () => _part.GetDependencies(descriptorAccessor), d =>
            {
                var partActivator = _part.GetActivator(d);
                CompositeActivator exportActivator = (c, o) => ((ComposablePart)partActivator(c, o)).GetExportedValue(_export);
                return ExportDescriptor.Create(exportActivator, _export.Metadata);
            }));
        }
예제 #20
0
        public override CompositeActivator RewriteActivator(
            TypeInfo partType,
            CompositeActivator activator,
            IDictionary <string, object> partMetadata,
            IEnumerable <CompositionDependency> dependencies)
        {
            if (!typeof(IDisposable).GetTypeInfo().IsAssignableFrom(partType))
            {
                return(activator);
            }

            return((c, o) =>
            {
                var inst = (IDisposable)activator(c, o);
                c.AddBoundInstance(inst);
                return inst;
            });
        }
예제 #21
0
        /// <summary>
        /// Execute a new composition operation starting within the specified lifetime
        /// context, for the specified activator.
        /// </summary>
        /// <param name="outermostLifetimeContext">Context in which to begin the operation (the operation can flow
        /// to the parents of the context if required).</param>
        /// <param name="compositionRootActivator">Activator that will drive the operation.</param>
        /// <returns>The composed object graph.</returns>
        public static object Run(LifetimeContext outermostLifetimeContext, CompositeActivator compositionRootActivator)
        {
            if (outermostLifetimeContext is null)
            {
                throw new ArgumentNullException(nameof(outermostLifetimeContext));
            }
            if (compositionRootActivator is null)
            {
                throw new ArgumentNullException(nameof(compositionRootActivator));
            }

            using (var operation = new CompositionOperation())
            {
                var result = compositionRootActivator(outermostLifetimeContext, operation);
                operation.Complete();
                return(result);
            }
        }
        public void GetDescriptor_CycleActivatorNotCompleted_ThrowsNotImplementedException()
        {
            ExportDescriptorPromise promise = null;

            promise = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => Enumerable.Empty <CompositionDependency>(), depdendencies =>
            {
                ExportDescriptor cycleDescriptor = promise.GetDescriptor();
                CompositeActivator activator     = cycleDescriptor.Activator;
                Assert.Throws <NotImplementedException>(() => activator(null, null));

                return(ExportDescriptor.Create(Activator, new Dictionary <string, object> {
                    { "key", "value" }
                }));
            });

            // Invoke the GetDescriptor method to start the test.
            Assert.NotNull(promise.GetDescriptor());
        }
        public void GetDescriptor_CycleActivatorNotCompleted_ThrowsInternalErrorException()
        {
            ExportDescriptorPromise promise = null;

            promise = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => Enumerable.Empty <CompositionDependency>(), depdendencies =>
            {
                ExportDescriptor cycleDescriptor = promise.GetDescriptor();
                CompositeActivator activator     = cycleDescriptor.Activator;
                Exception ex = Assert.ThrowsAny <Exception>(() => activator(null, null));
                Assert.Equal("Microsoft.Internal.Assumes+InternalErrorException", ex.GetType().ToString());

                return(ExportDescriptor.Create(Activator, new Dictionary <string, object> {
                    { "key", "value" }
                }));
            });

            // Invoke the GetDescriptor method to start the test.
            Assert.NotNull(promise.GetDescriptor());
        }
        public DelegateExportDescriptorProvider(Func<object> exportedInstanceFactory, Type contractType, string contractName, IDictionary<string, object> metadata, bool isShared)
            : base (contractType, contractName, metadata)
        {
            if (exportedInstanceFactory == null) throw new ArgumentNullException("exportedInstanceFactory");
            Contract.EndContractBlock();

            // Runs the factory method, validates the result and registers it for disposal if necessary.
            CompositeActivator constructor = (c, o) => {
                var result = exportedInstanceFactory();
                if (result == null)
                    throw new InvalidOperationException("Delegate factory returned null.");

                if (result is IDisposable)
                    c.AddBoundInstance((IDisposable)result);

                return result;
            };

            if (isShared)
            {
                var sharingId = LifetimeContext.AllocateSharingId();
                _activator = (c, o) => {
                    // Find the root composition scope.
                    var scope = c.FindContextWithin(null);
                    if (scope == c)
                    {
                        // We're already in the root scope, create the instance
                        return scope.GetOrCreate(sharingId, o, constructor);
                    }
                    else
                    {
                        // Composition is moving up the hierarchy of scopes; run
                        // a new operation in the root scope.
                        return CompositionOperation.Run(scope, (c1, o1) => c1.GetOrCreate(sharingId, o1, constructor));
                    }
                };
            }
            else
            {
                _activator = constructor;
            }
        }
        public void GetDescriptor_CycleActivatorCompleted_Success()
        {
            ExportDescriptorPromise promise   = null;
            CompositeActivator      activator = null;

            promise = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => Enumerable.Empty <CompositionDependency>(), depdendencies =>
            {
                ExportDescriptor cycleDescriptor = promise.GetDescriptor();
                activator = cycleDescriptor.Activator;

                return(ExportDescriptor.Create(Activator, new Dictionary <string, object> {
                    { "key", "value" }
                }));
            });

            ExportDescriptor descriptor = promise.GetDescriptor();

            Assert.Equal("hi", descriptor.Activator(null, null));
            Assert.Equal("hi", activator(null, null));
        }
예제 #26
0
        /// <summary>
        /// Either retrieve an existing part instance with the specified sharing id, or
        /// create and share a new part instance using <paramref name="creator"/> within
        /// <paramref name="operation"/>.
        /// </summary>
        /// <param name="sharingId">Sharing id for the part in question.</param>
        /// <param name="operation">Operation in which to activate a new part instance if necessary.</param>
        /// <param name="creator">Activator that can activate a new part instance if necessary.</param>
        /// <returns>The part instance corresponding to <paramref name="sharingId"/> within this lifetime context.</returns>
        /// <remarks>This method is lock-free if the part instance already exists. If the part instance must be created,
        /// a lock will be taken that will serialize other writes via this method (concurrent reads will continue to
        /// be safe and lock-free). It is important that the composition, and thus lock acquisition, is strictly
        /// leaf-to-root in the lifetime tree.</remarks>
        public object GetOrCreate(int sharingId, CompositionOperation operation, CompositeActivator creator)
        {
            object result;

            if (_sharedPartInstances != null && _sharedPartInstances.TryGetValue(sharingId, out result))
            {
                return(result);
            }

            // Remains locked for the rest of the operation.
            operation.EnterSharingLock(_sharingLock);

            if (_sharedPartInstances == null)
            {
                _sharedPartInstances = new SmallSparseInitonlyArray();
                _instancesUndergoingInitialization = new SmallSparseInitonlyArray();
            }
            else if (_sharedPartInstances.TryGetValue(sharingId, out result))
            {
                return(result);
            }

            // Already being initialized _on the same thread_.
            if (_instancesUndergoingInitialization.TryGetValue(sharingId, out result))
            {
                return(result);
            }

            result = creator(this, operation);

            _instancesUndergoingInitialization.Add(sharingId, result);

            operation.AddPostCompositionAction(() =>
            {
                _sharedPartInstances.Add(sharingId, result);
            });

            return(result);
        }
예제 #27
0
        public override CompositeActivator RewriteActivator(
            TypeInfo partType,
            CompositeActivator activator,
            IDictionary <string, object> partMetadata,
            IEnumerable <CompositionDependency> dependencies)
        {
            var result = activator;

            var partTypeAsType          = partType.AsType();
            var importsSatisfiedMethods = partTypeAsType.GetRuntimeMethods()
                                          .Where(mi => _attributeContext.GetDeclaredAttribute <OnImportsSatisfiedAttribute>(mi.DeclaringType, mi) != null);

            foreach (var m in importsSatisfiedMethods)
            {
                if (!(m.IsPublic || m.IsAssembly) | m.IsStatic || m.ReturnType != typeof(void) ||
                    m.IsGenericMethodDefinition || m.GetParameters().Length != 0)
                {
                    var message = string.Format(
                        Properties.Resources.OnImportsSatisfiedFeature_AttributeError,
                        partType, m.Name);
                    throw new CompositionFailedException(message);
                }

                var ois  = Expression.Parameter(typeof(object), "ois");
                var call = Expression.Lambda <Action <object> >(
                    Expression.Call(Expression.Convert(ois, partType.AsType()), m), ois).Compile();

                var prev = result;
                result = (c, o) =>
                {
                    var psn = prev(c, o);
                    o.AddPostCompositionAction(() => call(psn));
                    return(psn);
                };
            }

            return(result);
        }
예제 #28
0
        public override CompositeActivator RewriteActivator(
            TypeInfo partType,
            CompositeActivator activator,
            IDictionary<string, object> partMetadata,
            IEnumerable<CompositionDependency> dependencies)
        {
            var result = activator;

            var partTypeAsType = partType.AsType();
            var importsSatisfiedMethods = partTypeAsType.GetRuntimeMethods()
                .Where(mi => _attributeContext.GetDeclaredAttribute<OnImportsSatisfiedAttribute>(mi.DeclaringType, mi) != null);

            foreach (var m in importsSatisfiedMethods)
            {
                if (!(m.IsPublic || m.IsAssembly) | m.IsStatic || m.ReturnType != typeof(void) ||
                    m.IsGenericMethodDefinition || m.GetParameters().Length != 0)
                {
                    var message = string.Format(
                        Properties.Resources.OnImportsSatisfiedFeature_AttributeError,
                        partType, m.Name);
                    throw new CompositionFailedException(message);
                }

                var ois = Expression.Parameter(typeof(object), "ois");
                var call = Expression.Lambda<Action<object>>(
                    Expression.Call(Expression.Convert(ois, partType.AsType()), m), ois).Compile();

                var prev = result;
                result = (c, o) =>
                {
                    var psn = prev(c, o);
                    o.AddPostCompositionAction(() => call(psn));
                    return psn;
                };
            }

            return result;
        }
예제 #29
0
        /// <summary>
        /// Either retrieve an existing part instance with the specified sharing id, or
        /// create and share a new part instance using <paramref name="creator"/> within
        /// <paramref name="operation"/>.
        /// </summary>
        /// <param name="sharingId">Sharing id for the part in question.</param>
        /// <param name="operation">Operation in which to activate a new part instance if necessary.</param>
        /// <param name="creator">Activator that can activate a new part instance if necessary.</param>
        /// <returns>The part instance corresponding to <paramref name="sharingId"/> within this lifetime context.</returns>
        /// <remarks>This method is lock-free if the part instance already exists. If the part instance must be created,
        /// a lock will be taken that will serialize other writes via this method (concurrent reads will continue to
        /// be safe and lock-free). It is important that the composition, and thus lock acquisition, is strictly
        /// leaf-to-root in the lifetime tree.</remarks>
        public object GetOrCreate(int sharingId, CompositionOperation operation, CompositeActivator creator)
        {
            object result;
            if (_sharedPartInstances != null && _sharedPartInstances.TryGetValue(sharingId, out result))
                return result;

            // Remains locked for the rest of the operation.
            operation.EnterSharingLock(_sharingLock);

            if (_sharedPartInstances == null)
            {
                _sharedPartInstances = new SmallSparseInitonlyArray();
                _instancesUndergoingInitialization = new SmallSparseInitonlyArray();
            }
            else if (_sharedPartInstances.TryGetValue(sharingId, out result))
            {
                return result;
            }

            // Already being initialized _on the same thread_.
            if (_instancesUndergoingInitialization.TryGetValue(sharingId, out result))
                return result;

            result = creator(this, operation);

            _instancesUndergoingInitialization.Add(sharingId, result);

            operation.AddPostCompositionAction(() =>
            {
                _sharedPartInstances.Add(sharingId, result);
            });

            return result;
        }
예제 #30
0
 public DirectExportDescriptor(CompositeActivator activator !!, IDictionary <string, object> metadata !!)
 public object GetOrCreate(int sharingId, CompositionOperation operation, CompositeActivator creator);
 public static ExportDescriptor Create(CompositeActivator activator, IDictionary<string, object> metadata);
 public static object Run(LifetimeContext outermostLifetimeContext, CompositeActivator compositionRootActivator);
예제 #34
0
 protected abstract ExportDescriptor GetExportDescriptor(CompositeActivator partActivator);
예제 #35
0
 /// <summary>
 /// Construct an <see cref="ExportDescriptor"/>.
 /// </summary>
 /// <param name="activator">The activator used to retrieve instances of the export.</param>
 /// <param name="metadata">The Export Metadata associated with the export.</param>
 /// <returns>The export descriptor.</returns>
 public static ExportDescriptor Create(CompositeActivator activator, IDictionary <string, object> metadata)
 {
     return(new DirectExportDescriptor(activator, metadata));
 }
예제 #36
0
 protected override ExportDescriptor GetExportDescriptor(CompositeActivator partActivator)
 {
     return ExportDescriptor.Create(partActivator, Metadata);
 }
 protected override ExportDescriptor GetExportDescriptor(CompositeActivator partActivator)
 {
     return(ExportDescriptor.Create(partActivator, Metadata));
 }
예제 #38
0
 protected abstract ExportDescriptor GetExportDescriptor(CompositeActivator partActivator);
예제 #39
0
 /// <summary>
 /// Construct an <see cref="ExportDescriptor"/>.
 /// </summary>
 /// <param name="activator">The activator used to retrieve instances of the export.</param>
 /// <param name="metadata">The Export Metadata associated with the export.</param>
 /// <returns>The export descriptor.</returns>
 public static ExportDescriptor Create(CompositeActivator activator, IDictionary<string, object> metadata)
 {
     return new DirectExportDescriptor(activator, metadata);
 }
예제 #40
0
 /// <summary>
 /// Participate in the activator creation process.
 /// </summary>
 /// <param name="partType">The part type being activated.</param>
 /// <param name="activator">The activator body so far.</param>
 /// <param name="partMetadata">Metadata associated with the part being activated.</param>
 /// <param name="dependencies">Dependencies returned by a previous call to <see cref="GetDependencies"/>.</param>
 /// <returns>A new activator body, or the one already provided.</returns>
 public abstract CompositeActivator RewriteActivator(
     TypeInfo partType,
     CompositeActivator activator,
     IDictionary<string, object> partMetadata,
     IEnumerable<CompositionDependency> dependencies);
예제 #41
0
        public CompositeActivator GetActivator(DependencyAccessor definitionAccessor, IEnumerable<CompositionDependency> dependencies)
        {
            if (_partActivator != null) return _partActivator;

            var contextParam = Expression.Parameter(typeof(LifetimeContext), "cc");
            var operationParm = Expression.Parameter(typeof(CompositionOperation), "op");

            var cps = _constructor.GetParameters();
            Expression[] paramActivatorCalls = new Expression[cps.Length];

            var partActivatorDependencies = dependencies
                .Where(dep => dep.Site is ParameterImportSite)
                .ToDictionary(d => ((ParameterImportSite)d.Site).Parameter);

            for (var i = 0; i < cps.Length; ++i)
            {
                var pi = cps[i];
                CompositionDependency dep;

                if (partActivatorDependencies.TryGetValue(pi, out dep))
                {
                    var a = dep.Target.GetDescriptor().Activator;
                    paramActivatorCalls[i] =
                        Expression.Convert(Expression.Call(Expression.Constant(a), s_activatorInvoke, contextParam, operationParm), pi.ParameterType);
                }
                else
                {
                    paramActivatorCalls[i] = Expression.Default(pi.ParameterType);
                }
            }

            Expression body = Expression.Convert(Expression.New(_constructor, paramActivatorCalls), typeof(object));

            var activator = Expression
                .Lambda<CompositeActivator>(body, contextParam, operationParm)
                .Compile();

            foreach (var activationFeature in _activationFeatures)
                activator = activationFeature.RewriteActivator(_partType, activator, _partMetadata.Value, dependencies);

            _partActivator = activator;
            return _partActivator;
        }
        // The source will only be asked for parts once per exportKey, but it is the
        // source's responsibility to return the same part multiple times when that part
        // has more than one export (not shown here.)
        //
        public override IEnumerable <ExportDescriptorPromise> GetExportDescriptors(CompositionContract contract, DependencyAccessor definitionAccessor)
        {
            if (contract.Equals(new CompositionContract(typeof(RequestListener))))
            {
                return new[] { RequestListenerPart(contract, definitionAccessor) }
            }
            ;

            if (contract.Equals(new CompositionContract(typeof(ConsoleLog))))
            {
                return new[] { ConsoleLogPart(contract, definitionAccessor) }
            }
            ;

            return(NoExportDescriptors);
        }

        // Console log is a disposable singleton (no boundaries)
        // that exports itself under its own concrete type.
        //
        ExportDescriptorPromise ConsoleLogPart(CompositionContract contract, DependencyAccessor definitionAccessor)
        {
            return(new ExportDescriptorPromise(
                       contract,
                       typeof(ConsoleLog).Name,
                       true,
                       NoDependencies,
                       _ =>
            {
                var sharingId = LifetimeContext.AllocateSharingId();

                return ExportDescriptor.Create((c, o) =>
                {
                    CompositeActivator activatorBody = (sc, so) =>
                    {
                        var result = new ConsoleLog();
                        c.AddBoundInstance(result);
                        return result;
                    };

                    var scope = c.FindContextWithin(null);
                    if (object.ReferenceEquals(scope, c))
                    {
                        return scope.GetOrCreate(sharingId, o, activatorBody);
                    }
                    else
                    {
                        return CompositionOperation.Run(scope, (c1, o1) => c1.GetOrCreate(sharingId, o1, activatorBody));
                    }
                }, NoMetadata);
            }));
        }

        // Non-shared part that exports itself and has a dependency on ConsoleLog.
        //
        ExportDescriptorPromise RequestListenerPart(CompositionContract contract, DependencyAccessor definitionAccessor)
        {
            return(new ExportDescriptorPromise(
                       contract,
                       typeof(RequestListener).Name,
                       false,
                       () => new[] { definitionAccessor.ResolveRequiredDependency("log", new CompositionContract(typeof(Lazy <ConsoleLog>)), true) },
                       dependencies =>
            {
                var logActivator = dependencies.Single().Target.GetDescriptor().Activator;
                return ExportDescriptor.Create((c, o) =>
                {
                    var log = (Lazy <ConsoleLog>)logActivator(c, o);
                    return new RequestListener(log);
                }, NoMetadata);
            }));
        }
    }
}
예제 #43
0
 /// <summary>
 /// Participate in the activator creation process.
 /// </summary>
 /// <param name="partType">The part type being activated.</param>
 /// <param name="activator">The activator body so far.</param>
 /// <param name="partMetadata">Metadata associated with the part being activated.</param>
 /// <param name="dependencies">Dependencies returned by a previous call to <see cref="GetDependencies"/>.</param>
 /// <returns>A new activator body, or the one already provided.</returns>
 public abstract CompositeActivator RewriteActivator(
     TypeInfo partType,
     CompositeActivator activator,
     IDictionary <string, object> partMetadata,
     IEnumerable <CompositionDependency> dependencies);