internal MutableAmbientProperty(MutableItem owner, AmbientPropertyInfo info)
     : base(owner, StObjMutableReferenceKind.AmbientProperty)
 {
     _info      = info;
     Type       = _info.PropertyType;
     IsOptional = _info.IsOptional;
 }
 /// <summary>
 /// Initializes a new marker object: the ambient property has not been found.
 /// A marker is not used.
 /// </summary>
 internal MutableAmbientProperty(MutableItem owner, string unexistingPropertyName)
     : base(owner, StObjMutableReferenceKind.AmbientProperty)
 {
     _info      = null !;
     Type       = typeof(object);
     IsOptional = false;
     _maxSpecializationDepthSet = Int32.MaxValue;
 }
        protected override void SetGeneralizationInfo(IActivityMonitor monitor, CovariantPropertyInfo g)
        {
            base.SetGeneralizationInfo(monitor, g);

            AmbientPropertyInfo gen = (AmbientPropertyInfo)g;

            if (!_isSourceDefined)
            {
                ResolutionSource = gen.ResolutionSource;
            }
            // Captures the Generalization.
            // We keep the fact that this property overrides one above (errors have been logged if conflict/incoherency occur).
            // We can keep the Generalization but not a reference to the specialization since we are
            // not Contextualized here, but only on a pure Type level.
            Generalization = gen;
        }
        /// <summary>
        /// An ambient property must be public or protected in order to be "specialized" either by overriding (for virtual ones)
        /// or by masking ('new' keyword in C#), typically to support covariance return type.
        /// The "Property Covariance" trick can be supported here because ambient properties are conceptually "read only" properties:
        /// they must be settable only to enable the framework (and no one else) to actually set their values.
        /// </summary>
        static public void CreateAmbientPropertyListForExactType(
            IActivityMonitor monitor,
            Type t,
            int definerSpecializationDepth,
            List <StObjPropertyInfo> stObjProperties,
            out IList <AmbientPropertyInfo>?apListResult,
            out IList <InjectObjectInfo>?injectedListResult)
        {
            Debug.Assert(stObjProperties != null);

            var properties = t.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)
                             .Where(p => !p.Name.Contains('.', StringComparison.Ordinal));

            apListResult       = null;
            injectedListResult = null;
            foreach (var p in properties)
            {
                StObjPropertyAttribute?stObjAttr = p.GetCustomAttribute <StObjPropertyAttribute>(false);
                if (stObjAttr != null)
                {
                    string nP = String.IsNullOrEmpty(stObjAttr.PropertyName) ? p.Name : stObjAttr.PropertyName;
                    Type   tP = stObjAttr.PropertyType == null ? p.PropertyType : stObjAttr.PropertyType;
                    if (stObjProperties.Find(sp => sp.Name == nP) != null)
                    {
                        monitor.Error($"StObj property named '{p.Name}' for '{p.DeclaringType}' is defined more than once. It should be declared only once.");
                        continue;
                    }
                    stObjProperties.Add(new StObjPropertyInfo(t, stObjAttr.ResolutionSource, nP, tP, p));
                    // Continue to detect Ambient properties. Properties that are both Ambient and StObj must be detected.
                }
                AmbientPropertyAttribute?ap = p.GetCustomAttribute <AmbientPropertyAttribute>(false);
                IAmbientPropertyOrInjectObjectAttribute?ac = p.GetCustomAttribute <InjectObjectAttribute>(false);
                if (ac != null || ap != null)
                {
                    if (stObjAttr != null || (ac != null && ap != null))
                    {
                        monitor.Error($"Property named '{p.Name}' for '{p.DeclaringType}' can not be both an Ambient Singleton, an Ambient Property or a StObj property.");
                        continue;
                    }
                    IAmbientPropertyOrInjectObjectAttribute attr = ac ?? ap !;
                    string kindName = attr.IsAmbientProperty ? AmbientPropertyInfo.KindName : InjectObjectInfo.KindName;

                    var mGet = p.GetGetMethod(true);
                    if (mGet == null || mGet.IsPrivate)
                    {
                        monitor.Error($"Property '{p.Name}' of '{p.DeclaringType}' can not be marked as {kindName}. Did you forget to make it protected or public?");
                        continue;
                    }
                    if (attr.IsAmbientProperty)
                    {
                        Debug.Assert(ap != null);
                        if (apListResult == null)
                        {
                            apListResult = new List <AmbientPropertyInfo>();
                        }
                        var amb = new AmbientPropertyInfo(p, attr.IsOptionalDefined, attr.IsOptional, ap.IsResolutionSourceDefined, ap.ResolutionSource, definerSpecializationDepth, apListResult.Count);
                        apListResult.Add(amb);
                    }
                    else
                    {
                        if (injectedListResult == null)
                        {
                            injectedListResult = new List <InjectObjectInfo>();
                        }
                        var amb = new InjectObjectInfo(p, attr.IsOptionalDefined, attr.IsOptional, definerSpecializationDepth, injectedListResult.Count);
                        injectedListResult.Add(amb);
                    }
                }
            }
        }
 internal TrackedAmbientPropertyInfo(MutableItem o, AmbientPropertyInfo p)
 {
     Owner = o;
     AmbientPropertyInfo = p;
 }