コード例 #1
0
 internal AutoServiceKind ComputeFinalTypeKind(IActivityMonitor m, IAutoServiceKindComputeFacade kindComputeFacade, ref bool success)
 {
     if (!_isComputed)
     {
         if (_isComputing)
         {
             m.Warn($"Automatic DI type of 'IEnumerable<{EnumeratedType.FullName}> is not decidable: a dependency cycle has been found. It will be considered as the \"worst case\": a non marshallable IsFrontService|IsScoped.");
             _finalKind = AutoServiceKind.IsFrontService | AutoServiceKind.IsFrontProcessService | AutoServiceKind.IsScoped;
         }
         else
         {
             // Check that the potential registered IEnumerable AutoServiceKind is compatible with the one of the enumerated interface.
             var combined = (_itemKind | _enumerabledKind) & ~CKTypeKind.IsMultipleService;
             var conflict = combined.GetCombinationError(false);
             if (conflict != null)
             {
                 m.Error($"Invalid configuration for 'IEnumerable<{EnumeratedType.FullName}>' ({_enumerabledKind}) that contradicts the {EnumeratedType.Name} interface ({_itemKind}): {conflict}.");
                 success = false;
             }
             else
             {
                 _isComputing = true;
                 DoComputeFinalTypeKind(m, kindComputeFacade, combined.ToAutoServiceKind(), ref success);
                 _isComputing = false;
             }
         }
         _isComputed = true;
     }
     return(_finalKind);
 }
コード例 #2
0
 public FinalRegistrar(
     IActivityMonitor monitor,
     StObjObjectEngineMap engineMap,
     IAutoServiceKindComputeFacade kindComputeFacade)
 {
     _monitor           = monitor;
     _engineMap         = engineMap;
     _infos             = new Dictionary <AutoServiceClassInfo, BuildClassInfo>();
     _kindComputeFacade = kindComputeFacade;
 }
コード例 #3
0
 internal CKTypeCollectorResult(ISet <Assembly> assemblies,
                                IPocoSupportResult?pocoSupport,
                                RealObjectCollectorResult c,
                                AutoServiceCollectorResult s,
                                IReadOnlyDictionary <Type, TypeAttributesCache?> regularTypes,
                                IAutoServiceKindComputeFacade kindComputeFacade)
 {
     PocoSupport       = pocoSupport;
     Assemblies        = assemblies;
     RealObjects       = c;
     AutoServices      = s;
     _regularTypes     = regularTypes;
     KindComputeFacade = kindComputeFacade;
 }
コード例 #4
0
 public IStObjServiceFinalManualMapping?GetFinalMapping(
     IActivityMonitor m,
     StObjObjectEngineMap engineMap,
     IAutoServiceKindComputeFacade kindComputeFacade,
     ref bool success)
 {
     if (!_finalMappingDone)
     {
         _finalMappingDone = true;
         Class.ComputeFinalTypeKind(m, kindComputeFacade, new Stack <AutoServiceClassInfo>(), ref success);
         if (Assignments.Any())
         {
             _finalMapping = engineMap.CreateServiceFinalManualMapping(this);
         }
     }
     return(_finalMapping);
 }
コード例 #5
0
            bool DoComputeFinalTypeKind(IActivityMonitor m, IAutoServiceKindComputeFacade ctx, AutoServiceKind initial, ref bool success)
            {
                Debug.Assert(_rawImpls != null);

                const AutoServiceKind FrontTypeMask = AutoServiceKind.IsFrontProcessService | AutoServiceKind.IsFrontService;

                bool           isScoped               = (initial & AutoServiceKind.IsScoped) != 0;
                HashSet <Type>?allMarshallableTypes   = null;
                HashSet <Type>?frontMarshallableTypes = null;
                // If it is [IsMarshallable], the marshaller must handle the marhsalling of any implementations
                // (this is strange... but who knows?).
                bool isInterfaceMarshallable = (initial & AutoServiceKind.IsMarshallable) != 0;

                // If isInterfaceMarshallable is false (regular case), then for this IEnumerable to be marshallable, all its
                // implementations that are Front services must be marshallable so that it can be resolved as long as its
                // implementations have been marshalled.
                // Lets's be optimistic: all implementations that are Front(Process) services (if any) will be marshallable.
                bool isAutomaticallyMarshallable = true;

                using (m.OpenTrace($"Computing 'IEnumerable<{EnumeratedType.FullName}>'s final type from {_rawImpls.Count} implementations. Initial: '{initial}'."))
                {
                    foreach (var info in _rawImpls)
                    {
                        // RealObject are singleton, are not mashallable and not front process.
                        if (info is RealObjectClassInfo)
                        {
                            continue;
                        }

                        Debug.Assert(info.ServiceClass != null);
                        var impl = info.ServiceClass.MostSpecialized;
                        Debug.Assert(impl != null);
                        // We provide a new empty "cycle detection context" to the class constructors: IEnumerable
                        // of interfaces break potential cycles since they handle their own cycle by resolving to
                        // the "worst" non marshallable IsFrontService|IsScoped.
                        // We consider that if the IEnumerable (or one of its class) cannot be resolved by the DI container,
                        // it's not our problem here.
                        var k = impl.ComputeFinalTypeKind(m, ctx, new Stack <AutoServiceClassInfo>(), ref success);
                        // Check for scope lifetime.
                        if (!isScoped)
                        {
                            if ((k & AutoServiceKind.IsScoped) != 0)
                            {
                                if ((initial & AutoServiceKind.IsSingleton) != 0)
                                {
                                    m.Error($"Lifetime error: Type 'IEnumerable<{EnumeratedType.FullName}>' has been registered as a Singleton but implementation '{impl.ClassType}' is Scoped.");
                                    success = false;
                                }
                                else
                                {
                                    isScoped = true;
                                    m.Info($"Type 'IEnumerable<{EnumeratedType.FullName}>' must be Scoped since the implementation '{impl.ClassType}' is Scoped.");
                                }
                            }
                        }
                        // If the implementation is not a front service, we skip it (we don't care of a IsMarshallable only type).
                        if ((k & (AutoServiceKind.IsFrontService | AutoServiceKind.IsFrontProcessService)) == 0)
                        {
                            continue;
                        }

                        var newFinal = _finalKind | (k & AutoServiceKind.IsFrontProcessService | AutoServiceKind.IsFrontService);
                        if (newFinal != _finalKind)
                        {
                            // Upgrades from None, Process to Front...
                            m.Trace($"Type 'IEnumerable<{EnumeratedType.FullName}>' must be {newFinal & FrontTypeMask}, because of (at least) '{impl.ClassType}' implementation.");
                            _finalKind = newFinal;
                        }
                        // If the enumerated Service is marshallable at its level OR it is already known to be NOT automatically marshallable,
                        // we don't have to worry anymore about the subsequent implementations marshalling.
                        if (isInterfaceMarshallable || !isAutomaticallyMarshallable)
                        {
                            continue;
                        }

                        if ((k & AutoServiceKind.IsMarshallable) == 0)
                        {
                            if (success)
                            {
                                m.Warn($"Type 'IEnumerable<{EnumeratedType.FullName}>' is not marshallable and the implementation '{impl.ClassType}' that is a Front service is not marshallable: 'IEnumerable<{EnumeratedType.Name}>' cannot be considered as marshallable.");
                            }
                            isAutomaticallyMarshallable = false;
                        }
                        else
                        {
                            if (allMarshallableTypes == null)
                            {
                                allMarshallableTypes = new HashSet <Type>();
                            }
                            Debug.Assert(impl.MarshallableTypes != null, "EnsureCtorBinding has been called.");
                            allMarshallableTypes.AddRange(impl.MarshallableTypes);
                            if ((k & AutoServiceKind.IsFrontService) != 0)
                            {
                                if (frontMarshallableTypes == null)
                                {
                                    frontMarshallableTypes = new HashSet <Type>();
                                }
                                Debug.Assert(impl.MarshallableInProcessTypes != null, "EnsureCtorBinding has been called.");
                                frontMarshallableTypes.AddRange(impl.MarshallableInProcessTypes);
                            }
                        }
                    }
                    // Conclude about lifetime.
                    if (!isScoped)
                    {
                        if (success && (initial & AutoServiceKind.IsSingleton) == 0)
                        {
                            m.Info($"Nothing prevents 'IEnumerable<{EnumeratedType.FullName}>' to be considered as a Singleton: this is the most efficient choice.");
                        }
                        _finalKind |= AutoServiceKind.IsSingleton;
                    }
                    else
                    {
                        _finalKind |= AutoServiceKind.IsScoped;
                    }
                    // Conclude about Front aspect.
                    if (isInterfaceMarshallable)
                    {
                        MarshallableTypes = MarshallableInProcessTypes = new[] { EnumeratedType };
                        Debug.Assert((_finalKind & AutoServiceKind.IsMarshallable) == 0);
                    }
                    else
                    {
                        if (isAutomaticallyMarshallable && allMarshallableTypes != null)
                        {
                            Debug.Assert(allMarshallableTypes.Count > 0);
                            MarshallableTypes = allMarshallableTypes;
                            _finalKind       |= AutoServiceKind.IsMarshallable;
                            if (frontMarshallableTypes != null)
                            {
                                MarshallableInProcessTypes = frontMarshallableTypes;
                            }
                            else
                            {
                                MarshallableInProcessTypes = Type.EmptyTypes;
                            }
                        }
                        else
                        {
                            // This service is not a Front service OR it is not automatically marshallable.
                            // We have nothing special to do: the set of Marshallable types is empty (this is not an error).
                            MarshallableTypes = MarshallableInProcessTypes = Type.EmptyTypes;
                            Debug.Assert((_finalKind & AutoServiceKind.IsMarshallable) == 0);
                        }
                    }
                    if (_finalKind != initial)
                    {
                        m.CloseGroup($"Final: {_finalKind}");
                    }
                }

                return(success);
            }