public void Apply(ApplierContext context)
 {
     _services.Add(new ServiceDescriptor(
                       context.As,
                       context.Service,
                       Convert(context.Lifetime)));
 }
Esempio n. 2
0
        bool CopyNeeded(ResolvedTraitSet traits, ResolveOptions resOpt, CdmAttributeResolutionGuidance resGuide, List <AttributeResolutionApplier> actions)
        {
            if (actions == null || actions.Count == 0)
            {
                return(false);
            }

            // for every attribute in the set, detect if a merge of traits will alter the traits. if so, need to copy the attribute set to avoid overwrite
            int l = this.Set.Count;

            for (int i = 0; i < l; i++)
            {
                ResolvedAttribute resAtt = this.Set[i];
                foreach (var currentTraitAction in actions)
                {
                    ApplierContext ctx = new ApplierContext {
                        ResOpt = resOpt, ResAttSource = resAtt, ResGuide = resGuide
                    };
                    if (currentTraitAction.WillAttributeModify(ctx))
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
Esempio n. 3
0
        public void Apply_Lifetime()
        {
            // Arrange
            var services = CreateServices();
            var applier  = Create(services);
            var context  = new ApplierContext(typeof(Service1), new AddToServicesAttribute(Lifetime.Transient));

            // Act
            applier.Apply(context);

            // Assert
            services.Should().Contain(sd => sd.Lifetime == ServiceLifetime.Transient);
        }
Esempio n. 4
0
        public void Apply_Default()
        {
            // Arrange
            var services = CreateServices();
            var applier  = Create(services);
            var context  = new ApplierContext(typeof(Service1), new AddToServicesAttribute());

            // Act
            applier.Apply(context);

            // Assert
            services.Should().Contain(sd =>
                                      sd.ServiceType == typeof(Service1) && sd.Lifetime == ServiceLifetime.Scoped);
        }
Esempio n. 5
0
        public void Apply_Multiple()
        {
            // Arrange
            var services = CreateServices();
            var applier  = Create(services);
            var context  = new ApplierContext(typeof(Service1), new AddToServicesAttribute(Lifetime.Scoped, typeof(IService1)));

            // Act
            applier.Apply(context);

            // Assert
            services.Should().Contain(sd =>
                                      sd.ServiceType == typeof(IService1) &&
                                      sd.ImplementationType == typeof(Service1));
        }
Esempio n. 6
0
        public void Apply_As()
        {
            // Arrange
            var builder = CreateBuilder();
            var applier = Create(builder);
            var context = new ApplierContext(typeof(Service1), new AddToServicesAttribute(Lifetime.Transient, typeof(IService1)));

            // Act
            applier.Apply(context);

            // Assert
            var container = builder.Build();

            container.Resolve <IService1>().Should().NotBeNull().And.BeOfType <Service1>();
        }
        public void Apply_Default()
        {
            // Arrange
            var builder = CreateBuilder();
            var applier = Create(builder);
            var context = new ApplierContext(typeof(Service1), typeof(Service1), Lifetime.Transient);

            // Act
            applier.Apply(context);

            // Assert
            var container = builder.Build();

            container.Resolve <Service1>().Should().NotBeNull();
        }
Esempio n. 8
0
 public void Apply(ApplierContext context)
 {
     if (context.ForwardTo == null)
     {
         _services.Add(new ServiceDescriptor(
                           context.Service,
                           context.Implementation,
                           Convert(context.Lifetime)));
     }
     else
     {
         _services.Add(new ServiceDescriptor(
                           context.Service,
                           provider => provider.GetService(context.ForwardTo),
                           Convert(context.Lifetime)));
     }
 }
Esempio n. 9
0
        public void Apply_FowardTo()
        {
            // Arrange
            var services = CreateServices();
            var applier  = Create(services);
            var context1 = new ApplierContext(typeof(IMultipleImplementedInterfaces1), typeof(MultipleImplementedInterfaces), null, Lifetime.Scoped);
            var context2 = new ApplierContext(typeof(IMultipleImplementedInterfaces2), typeof(MultipleImplementedInterfaces), typeof(IMultipleImplementedInterfaces1), Lifetime.Scoped);

            // Act
            applier.Apply(context1);
            applier.Apply(context2);

            // Assert
            var serviceProvider = services.BuildServiceProvider();
            var _1 = serviceProvider.GetService <IMultipleImplementedInterfaces1>();
            var _2 = serviceProvider.GetService <IMultipleImplementedInterfaces2>();

            _1.Should().BeSameAs(_2);
        }
Esempio n. 10
0
        public void Apply_FowardTo()
        {
            // Arrange
            var builder  = CreateBuilder();
            var applier  = Create(builder);
            var context1 = new ApplierContext(typeof(IMultipleImplementedInterfaces1), typeof(MultipleImplementedInterfaces), null, Lifetime.Scoped);
            var context2 = new ApplierContext(typeof(IMultipleImplementedInterfaces2), typeof(MultipleImplementedInterfaces), typeof(IMultipleImplementedInterfaces1), Lifetime.Scoped);

            // Act
            applier.Apply(context1);
            applier.Apply(context2);

            // Assert
            var container = builder.Build();
            var _1        = container.Resolve <IMultipleImplementedInterfaces1>();
            var _2        = container.Resolve <IMultipleImplementedInterfaces2>();

            _1.Should().BeSameAs(_2);
        }
Esempio n. 11
0
        public void Apply(ApplierContext context)
        {
            var registration = _builder
                               .RegisterType(context.Service)
                               .As(context.As);

            switch (context.Lifetime)
            {
            case Lifetime.Singleton:
                registration.SingleInstance();
                break;

            case Lifetime.Scoped:
                registration.InstancePerLifetimeScope();
                break;

            case Lifetime.Transient:
                registration.InstancePerDependency();
                break;
            }
        }
Esempio n. 12
0
        public void Apply(ApplierContext context)
        {
            if (context.ForwardTo == null)
            {
                var registration = _builder
                                   .RegisterType(context.Implementation)
                                   .As(context.Service)
                                   .ConfigureLifecycle(context.Lifetime, null);
            }
            else
            {
                var registration = RegistrationBuilder.ForDelegate(context.Service, (c, parameters) =>
                {
                    return(c.Resolve(context.ForwardTo));
                })
                                   .ConfigureLifecycle(context.Lifetime, null)
                                   .CreateRegistration();

                _builder.RegisterComponent(registration);
            }
        }
Esempio n. 13
0
        public ResolvedAttributeSet RemoveRequestedAtts(Marker marker)
        {
            int countIndex = marker.CountIndex;
            int markIndex  = marker.MarkIndex;

            // for every attribute in the set run any attribute removers on the traits they have
            ResolvedAttributeSet appliedAttSet = new ResolvedAttributeSet();
            int l = this.Set.Count;

            for (int iAtt = 0; iAtt < l; iAtt++)
            {
                ResolvedAttribute resAtt = this.Set[iAtt];
                // possible for another set to be in this set
                ResolvedAttributeSet subSet = resAtt.Target as ResolvedAttributeSet;
                if (subSet?.Set != null)
                {
                    // well, that happened. so now we go around again on this same function and get rid of things from this group
                    marker.CountIndex = countIndex;
                    marker.MarkIndex  = markIndex;
                    ResolvedAttributeSet newSubSet = subSet.RemoveRequestedAtts(marker);
                    countIndex = marker.CountIndex;
                    markIndex  = marker.MarkIndex;
                    // replace the set with the new one that came back
                    resAtt.Target = newSubSet;
                    // if everything went away, then remove this group
                    if (newSubSet?.Set == null || newSubSet.Set.Count == 0)
                    {
                        resAtt = null;
                    }
                    else
                    {
                        // don't count this as an attribute (later)
                        countIndex--;
                    }
                }
                else
                {
                    // this is a good time to make the resolved names final
                    resAtt.previousResolvedName = resAtt.ResolvedName;
                    if (resAtt.Arc != null && resAtt.Arc.ApplierCaps != null && resAtt.Arc.ApplierCaps.CanRemove)
                    {
                        foreach (AttributeResolutionApplier apl in resAtt.Arc.ActionsRemove)
                        {
                            // this should look like the applier context when the att was created
                            ApplierContext ctx = new ApplierContext()
                            {
                                ResOpt = resAtt.Arc.ResOpt, ResAttSource = resAtt, ResGuide = resAtt.Arc.ResGuide
                            };
                            if (apl.WillRemove(ctx))
                            {
                                resAtt = null;
                                break;
                            }
                        }
                    }
                }
                if (resAtt != null)
                {
                    // attribute remains
                    // are we building a new set?
                    if (appliedAttSet != null)
                    {
                        this.CopyAttCtxMappingsInto(appliedAttSet.Ra2attCtxSet, appliedAttSet.AttCtx2ra, resAtt);
                        appliedAttSet.Merge(resAtt);
                    }
                    countIndex++;
                }
                else
                {
                    // remove the att
                    // if this is the first removed attribute, then make a copy of the set now
                    // after this point, the rest of the loop logic keeps the copy going as needed
                    if (appliedAttSet == null)
                    {
                        appliedAttSet = new ResolvedAttributeSet();
                        for (int iCopy = 0; iCopy < iAtt; iCopy++)
                        {
                            this.CopyAttCtxMappingsInto(appliedAttSet.Ra2attCtxSet, appliedAttSet.AttCtx2ra, this.Set[iCopy]);
                            appliedAttSet.Merge(this.Set[iCopy]);
                        }
                    }
                    // track deletes under the mark (move the mark up)
                    if (countIndex < markIndex)
                    {
                        markIndex--;
                    }
                }
            }

            marker.CountIndex = countIndex;
            marker.MarkIndex  = markIndex;

            // now we are that (or a copy)
            ResolvedAttributeSet rasResult = this;

            if (appliedAttSet != null && appliedAttSet.Size != rasResult.Size)
            {
                rasResult = appliedAttSet;
                rasResult.BaseTrait2Attributes = null;
                rasResult.AttributeContext     = this.AttributeContext;
            }

            return(rasResult);
        }
Esempio n. 14
0
        ResolvedAttributeSet Apply(ResolvedTraitSet traits, ResolveOptions resOpt, CdmAttributeResolutionGuidance resGuide, List <AttributeResolutionApplier> actions)
        {
            if (traits == null && actions.Count == 0)
            {
                // nothing can change
                return(this);
            }

            // for every attribute in the set run any attribute appliers
            ResolvedAttributeSet appliedAttSet = new ResolvedAttributeSet();
            int l = this.Set.Count;

            appliedAttSet.AttributeContext = this.AttributeContext;

            // check to see if we need to make a copy of the attributes
            // do this when building an attribute context and when we will modify the attributes (beyond traits)
            // see if any of the appliers want to modify
            bool makingCopy = false;

            if (l > 0 && appliedAttSet.AttributeContext != null && actions != null && actions.Count > 0)
            {
                ResolvedAttribute resAttTest = this.Set[0];
                foreach (AttributeResolutionApplier traitAction in actions)
                {
                    ApplierContext ctx = new ApplierContext {
                        ResOpt = resOpt, ResAttSource = resAttTest, ResGuide = resGuide
                    };
                    if (traitAction.WillAttributeModify(ctx) == true)
                    {
                        makingCopy = true;
                        break;
                    }
                }
            }

            if (makingCopy)
            {
                // fake up a generation round for these copies that are about to happen
                AttributeContextParameters acp = new AttributeContextParameters
                {
                    under = appliedAttSet.AttributeContext,
                    type  = Enums.CdmAttributeContextType.GeneratedSet,
                    Name  = "_generatedAttributeSet"
                };
                appliedAttSet.AttributeContext = CdmAttributeContext.CreateChildUnder(traits.ResOpt, acp);
                acp = new AttributeContextParameters
                {
                    under = appliedAttSet.AttributeContext,
                    type  = Enums.CdmAttributeContextType.GeneratedRound,
                    Name  = "_generatedAttributeRound0"
                };
                appliedAttSet.AttributeContext = CdmAttributeContext.CreateChildUnder(traits.ResOpt, acp);
            }
            for (int i = 0; i < l; i++)
            {
                ResolvedAttribute   resAtt        = this.Set[i];
                CdmAttributeContext attCtxToMerge = null;
                if (resAtt.Target is ResolvedAttributeSet subSet)
                {
                    if (makingCopy)
                    {
                        resAtt = resAtt.Copy();
                        // making a copy of a subset (att group) also bring along the context tree for that whole group
                        attCtxToMerge = resAtt.AttCtx;
                    }
                    // the set contains another set. process those
                    resAtt.Target = subSet.Apply(traits, resOpt, resGuide, actions);
                }
                else
                {
                    ResolvedTraitSet rtsMerge = resAtt.ResolvedTraits.MergeSet(traits);
                    resAtt.ResolvedTraits = rtsMerge;
                    if (actions != null)
                    {
                        foreach (AttributeResolutionApplier traitAction in actions)
                        {
                            ApplierContext ctx = new ApplierContext {
                                ResOpt = traits.ResOpt, ResAttSource = resAtt, ResGuide = resGuide
                            };
                            if (traitAction.WillAttributeModify(ctx) == true)
                            {
                                // make a context for this new copy
                                if (makingCopy)
                                {
                                    AttributeContextParameters acp = new AttributeContextParameters
                                    {
                                        under     = appliedAttSet.AttributeContext,
                                        type      = Enums.CdmAttributeContextType.AttributeDefinition,
                                        Name      = resAtt.ResolvedName,
                                        Regarding = resAtt.Target
                                    };
                                    ctx.AttCtx    = CdmAttributeContext.CreateChildUnder(traits.ResOpt, acp);
                                    attCtxToMerge = ctx.AttCtx as CdmAttributeContext;
                                }

                                // make a copy of the resolved att
                                if (makingCopy)
                                {
                                    resAtt = resAtt.Copy();
                                }

                                ctx.ResAttSource = resAtt;
                                // modify it
                                traitAction.DoAttributeModify(ctx);
                            }
                        }
                    }
                }
                appliedAttSet.Merge(resAtt, attCtxToMerge);
            }

            appliedAttSet.AttributeContext = this.AttributeContext;

            if (!makingCopy)
            {
                // didn't copy the attributes or make any new context, so just take the old ones
                appliedAttSet.Ra2attCtxSet = this.Ra2attCtxSet;
                appliedAttSet.AttCtx2ra    = this.AttCtx2ra;
            }

            return(appliedAttSet);
        }
        private List <ResolvedAttribute> GetApplierGeneratedAttributes(AttributeResolutionContext arc, bool clearState, bool applyModifiers)
        {
            if (this.ResolvedAttributeSet?.Set == null || arc == null)
            {
                return(null);
            }

            AttributeResolutionApplierCapabilities caps = arc.ApplierCaps;

            if (caps == null || (!caps.CanAttributeAdd && !caps.CanGroupAdd && !caps.CanRoundAdd))
            {
                return(null);
            }

            List <ResolvedAttribute> resAttOut = new List <ResolvedAttribute>();

            // this function constructs a 'plan' for building up the resolved attributes that get generated from a set of traits being applied to
            // a set of attributes. it manifests the plan into an array of resolved attributes
            // there are a few levels of hierarchy to consider.
            // 1. once per set of attributes, the traits may want to generate attributes. this is an attribute that is somehow descriptive of the whole set,
            //    even if it has repeating patterns, like the count for an expanded array.
            // 2. it is possible that some traits (like the array expander) want to keep generating new attributes for some run. each time they do this is considered a 'round'
            //    the traits are given a chance to generate attributes once per round. every set gets at least one round, so these should be the attributes that
            //    describe the set of other attributes. for example, the foreign key of a relationship or the 'class' of a polymorphic type, etc.
            // 3. for each round, there are new attributes created based on the resolved attributes from the previous round (or the starting atts for this set)
            //    the previous round attribute need to be 'done' having traits applied before they are used as sources for the current round.
            // the goal here is to process each attribute completely before moving on to the next one

            // that may need to start out clean
            if (clearState)
            {
                List <ResolvedAttribute> toClear = this.ResolvedAttributeSet.Set;
                for (int i = 0; i < toClear.Count; i++)
                {
                    toClear[i].ApplierState = null;
                }
            }

            // make an attribute context to hold attributes that are generated from appliers
            // there is a context for the entire set and one for each 'round' of applications that happen
            var attCtxContainerGroup = this.ResolvedAttributeSet.AttributeContext;

            if (attCtxContainerGroup != null)
            {
                AttributeContextParameters acp = new AttributeContextParameters
                {
                    under = attCtxContainerGroup,
                    type  = Enums.CdmAttributeContextType.GeneratedSet,
                    Name  = "_generatedAttributeSet"
                };

                attCtxContainerGroup = CdmAttributeContext.CreateChildUnder(arc.ResOpt, acp);
            }
            var attCtxContainer = attCtxContainerGroup;

            Func <ResolvedAttribute, AttributeResolutionApplier, Func <ApplierContext, bool>, dynamic, string, ApplierContext> MakeResolvedAttribute = (resAttSource, action, queryAdd, doAdd, state) =>
            {
                ApplierContext appCtx = new ApplierContext
                {
                    State        = state,
                    ResOpt       = arc.ResOpt,
                    AttCtx       = attCtxContainer,
                    ResAttSource = resAttSource,
                    ResGuide     = arc.ResGuide
                };

                if ((resAttSource?.Target as ResolvedAttributeSet)?.Set != null)
                {
                    return(appCtx); // makes no sense for a group
                }
                // will something add
                if (queryAdd(appCtx))
                {
                    // may want to make a new attribute group
                    // make the 'new' attribute look like any source attribute for the duration of this call to make a context. there could be state needed
                    appCtx.ResAttNew = resAttSource;
                    if (this.ResolvedAttributeSet.AttributeContext != null && action.WillCreateContext?.Invoke(appCtx) == true)
                    {
                        action.DoCreateContext(appCtx);
                    }
                    // make a new resolved attribute as a place to hold results
                    appCtx.ResAttNew = new ResolvedAttribute(appCtx.ResOpt, null, null, (CdmAttributeContext)appCtx.AttCtx);
                    // copy state from source
                    if (resAttSource?.ApplierState != null)
                    {
                        appCtx.ResAttNew.ApplierState = resAttSource.ApplierState.Copy();
                    }
                    else
                    {
                        appCtx.ResAttNew.ApplierState = new ApplierState();
                    }
                    // if applying traits, then add the sets traits as a starting point
                    if (applyModifiers)
                    {
                        appCtx.ResAttNew.ResolvedTraits = arc.TraitsToApply.DeepCopy();
                    }
                    // make it
                    doAdd(appCtx);

                    // combine resolution guidence for this set with anything new from the new attribute
                    appCtx.ResGuideNew   = (appCtx.ResGuide as CdmAttributeResolutionGuidance).combineResolutionGuidance(appCtx.ResGuideNew as CdmAttributeResolutionGuidance);
                    appCtx.ResAttNew.Arc = new AttributeResolutionContext(arc.ResOpt, appCtx.ResGuideNew as CdmAttributeResolutionGuidance, appCtx.ResAttNew.ResolvedTraits);

                    if (applyModifiers)
                    {
                        // add the sets traits back in to this newly added one
                        appCtx.ResAttNew.ResolvedTraits = appCtx.ResAttNew.ResolvedTraits.MergeSet(arc.TraitsToApply);
                        // be sure to use the new arc, the new attribute may have added actions. For now, only modify and remove will get acted on because recursion. ugh.
                        // do all of the modify traits
                        if (appCtx.ResAttNew.Arc.ApplierCaps.CanAttributeModify)
                        {
                            // modify acts on the source and we should be done with it
                            appCtx.ResAttSource = appCtx.ResAttNew;
                            foreach (var modAct in appCtx.ResAttNew.Arc.ActionsModify)
                            {
                                if (modAct.WillAttributeModify(appCtx))
                                {
                                    modAct.DoAttributeModify(appCtx);
                                }
                            }
                        }
                    }
                    appCtx.ResAttNew.CompleteContext(appCtx.ResOpt);
                    // tie this new resolved att to the source via lineage
                    if (appCtx.ResAttNew.AttCtx != null && resAttSource != null && resAttSource.AttCtx != null && resAttSource.ApplierState?.Flex_remove != true)
                    {
                        if (resAttSource.AttCtx.Lineage?.Count > 0)
                        {
                            foreach (var lineage in resAttSource.AttCtx.Lineage)
                            {
                                appCtx.ResAttNew.AttCtx.AddLineage(lineage);
                            }
                        }
                        else
                        {
                            appCtx.ResAttNew.AttCtx.AddLineage(resAttSource.AttCtx);
                        }
                    }
                }
                return(appCtx);
            };

            // get the one time atts
            if (caps.CanGroupAdd)
            {
                if (arc.ActionsGroupAdd != null)
                {
                    foreach (var action in arc.ActionsGroupAdd)
                    {
                        ApplierContext appCtx = MakeResolvedAttribute(null, action, action.WillGroupAdd, action.DoGroupAdd, "group");
                        // save it
                        if (appCtx?.ResAttNew != null)
                        {
                            resAttOut.Add(appCtx.ResAttNew);
                        }
                    }
                }
            }


            // now starts a repeating pattern of rounds
            // first step is to get attribute that are descriptions of the round.
            // do this once and then use them as the first entries in the first set of 'previous' atts for the loop

            // make an attribute context to hold attributes that are generated from appliers in this round
            int round = 0;

            if (attCtxContainerGroup != null)
            {
                AttributeContextParameters acp = new AttributeContextParameters
                {
                    under = attCtxContainerGroup,
                    type  = Enums.CdmAttributeContextType.GeneratedRound,
                    Name  = "_generatedAttributeRound0"
                };

                attCtxContainer = CdmAttributeContext.CreateChildUnder(arc.ResOpt, acp);
            }

            List <ResolvedAttribute> resAttsLastRound = new List <ResolvedAttribute>();

            if (caps.CanRoundAdd)
            {
                if (arc.ActionsRoundAdd != null)
                {
                    foreach (var action in arc.ActionsRoundAdd)
                    {
                        ApplierContext appCtx = MakeResolvedAttribute(null, action, action.WillRoundAdd, action.DoRoundAdd, "round");
                        // save it
                        if (appCtx?.ResAttNew != null)
                        {
                            // overall list
                            resAttOut.Add(appCtx.ResAttNew);
                            // previous list
                            resAttsLastRound.Add(appCtx.ResAttNew);
                        }
                    }
                }
            }

            // the first per-round set of attributes is the set owned by this object
            resAttsLastRound.AddRange(this.ResolvedAttributeSet.Set);

            // now loop over all of the previous atts until they all say 'stop'
            if (resAttsLastRound.Count > 0)
            {
                int continues = 0;
                do
                {
                    continues = 0;
                    List <ResolvedAttribute> resAttThisRound = new List <ResolvedAttribute>();
                    if (caps.CanAttributeAdd)
                    {
                        for (int iAtt = 0; iAtt < resAttsLastRound.Count; iAtt++)
                        {
                            if (arc.ActionsAttributeAdd != null)
                            {
                                foreach (var action in arc.ActionsAttributeAdd)
                                {
                                    ApplierContext appCtx = MakeResolvedAttribute(resAttsLastRound[iAtt], action, action.WillAttributeAdd, action.DoAttributeAdd, "detail");
                                    // save it
                                    if (appCtx?.ResAttNew != null)
                                    {
                                        // overall list
                                        resAttOut.Add(appCtx.ResAttNew);
                                        resAttThisRound.Add(appCtx.ResAttNew);
                                        if (appCtx.Continue)
                                        {
                                            continues++;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    resAttsLastRound = resAttThisRound;

                    round++;
                    if (attCtxContainerGroup != null)
                    {
                        AttributeContextParameters acp = new AttributeContextParameters
                        {
                            under = attCtxContainerGroup,
                            type  = Enums.CdmAttributeContextType.GeneratedRound,
                            Name  = $"_generatedAttributeRound{round}"
                        };

                        attCtxContainer = CdmAttributeContext.CreateChildUnder(arc.ResOpt, acp);
                    }
                } while (continues > 0);
            }

            return(resAttOut);
        }