internal AutoServiceClassInfo(IActivityMonitor m, IServiceProvider serviceProvider, AutoServiceClassInfo?parent, Type t, bool isExcluded, RealObjectClassInfo?objectInfo) { Debug.Assert(objectInfo == null || objectInfo.ServiceClass == null, "If we are the associated Service, we must be the only one."); if (objectInfo != null) { TypeInfo = objectInfo; objectInfo.ServiceClass = this; } else { TypeInfo = new CKTypeInfo(m, parent?.TypeInfo, t, serviceProvider, isExcluded, this); } Debug.Assert(parent == null || ReferenceEquals(TypeInfo.Generalization, parent.TypeInfo), $"Gen={TypeInfo.Generalization}/Par={parent?.TypeInfo}"); if (parent != null) { SpecializationDepth = parent.SpecializationDepth + 1; } // Used only when this service is eventually a simple one. SimpleMappingListIndex = -1; }
internal void RegisterServiceFinalObjectMapping(Type t, CKTypeInfo typeInfo) { Debug.Assert(typeInfo is RealObjectClassInfo); var c = (RealObjectClassInfo)typeInfo; MutableItem mapping = c.AutoServiceImpl; if (mapping == null) { c.AutoServiceImpl = mapping = _map[typeInfo.Type]; _serviceRealObjects.Add(mapping); } _serviceToObjectMap.Add(t, mapping); }
internal bool IsAssignableFrom(CKTypeInfo child) { Debug.Assert(child != null); CKTypeInfo?c = child; do { if (c == this) { return(true); } }while((c = c.Generalization) != null); return(false); }
internal void RemoveSpecialization(CKTypeInfo child) { Debug.Assert(child.Generalization == this); if (_firstChild == child) { _firstChild = child._nextSibling; --_specializationCount; } else { var c = _firstChild; while (c != null && c._nextSibling != child) { c = c._nextSibling; } if (c != null) { c._nextSibling = child._nextSibling; --_specializationCount; } } }
internal void RegisterMultipleInterfaces(Type tI, CKTypeKind enumeratedKind, CKTypeInfo final) { if (!_multipleMappings.TryGetValue(tI, out var multiple)) { Debug.Assert(enumeratedKind.GetCombinationError(false) == null); // A IEnumerable of IScoped is scoped, a IEnumerable of ISingleton is singleton, a IEnumerable of IFrontProcessService is // itself a front process service. Even a IEnumerable of an interface that has been marked [IsMarshallable] is de facto marshallable. // We rely on this here. Type tEnumerable = typeof(IEnumerable <>).MakeGenericType(tI); if ((enumeratedKind & (CKTypeKind.IsFrontService | CKTypeKind.IsMarshallable)) == (CKTypeKind.IsFrontService | CKTypeKind.IsMarshallable)) { // Only if the T interface is a IFrontService (and hence a Scoped) and is marked with IsMarshallable attribute // can we avoid the implementations analyzis. Even if a IFrontService interface marked with IsMarshallable attribute should be rare, // we can benefit here from this minor (but logical) optimization. _multipleMappings.Add(tI, new MultipleImpl(tEnumerable, tI)); } else { // The IEnumerable itself may have been explicitly registered via SetAutoServiceKind. // We check its compatibility with its enumerated interface (there may be incoherences) later in the DoComputeFinalTypeKind. // Here we just check the "worst case": CKTypeKind enumKind = KindDetector.GetValidKind(_monitor, tEnumerable); Debug.Assert(enumKind.GetCombinationError(false) == null); if ((enumKind & (CKTypeKind.IsFrontService | CKTypeKind.IsMarshallable)) == (CKTypeKind.IsFrontService | CKTypeKind.IsMarshallable)) { _multipleMappings.Add(tI, new MultipleImpl(tEnumerable, tI)); } else { _multipleMappings.Add(tI, new MultipleImpl(tEnumerable, enumKind, tI, enumeratedKind, final)); } } } else { multiple.AddImpl(final); } }
internal MultipleImpl(Type tEnum, CKTypeKind enumerabledKind, Type tI, CKTypeKind iKind, CKTypeInfo first) { EnumerableType = tEnum; _enumerabledKind = enumerabledKind; EnumeratedType = tI; _itemKind = iKind; _rawImpls = new List <CKTypeInfo>(); _rawImpls.Add(first); // These properties are null until ComputeFinalTypeKind is called. // (Offensive) I prefer assuming this nullity here rather than setting empty arrays. MarshallableTypes = null !; MarshallableInProcessTypes = null !; }
internal void AddImpl(CKTypeInfo final) => _rawImpls?.Add(final);