public void Apply(ApplierContext context) { _services.Add(new ServiceDescriptor( context.As, context.Service, Convert(context.Lifetime))); }
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); }
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); }
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); }
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)); }
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(); }
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))); } }
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); }
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); }
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; } }
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); } }
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); }
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); }