示例#1
0
    /// <param name="buildStages">The sequence of build stages. See <see cref="Builder" /> for details.</param>
    /// <param name="patternTree">Build chain patterns tree used to find build actions to build a unit.</param>
    /// <param name="auxPatternTree">Additional build chain patterns tree, in opposite to <paramref name="patternTree"/> these patterns
    /// are passed to <paramref name="parentBuilders"/> if unit is being tried to build via parent builders.</param>
    /// <param name="parentBuilders">
    /// If unit is not built and <paramref name="parentBuilders" /> are provided, tries to build a unit using
    /// parent builders one by one in the order they passed into the constructor.
    /// </param>
    public BuildSession(object[] buildStages, IBuildChainPattern patternTree, IBuildChainPattern?auxPatternTree, IBuilder[]?parentBuilders)
    {
        _buildStages = buildStages ?? throw new ArgumentNullException(nameof(buildStages));
        if (buildStages.Length == 0)
        {
            throw new ArgumentException("Should contain at least one build stage", nameof(buildStages));
        }
        if (buildStages.Any(stage => stage is null))
        {
            throw new ArgumentException("Should not contain null values", nameof(buildStages));
        }
        if (buildStages.Length != buildStages.Distinct().Count())
        {
            throw new ArgumentException("Should not contain duplicate values", nameof(buildStages));
        }
        if (parentBuilders?.Any(_ => _ is null) == true)
        {
            throw new ArgumentException("Should not contain null values", nameof(parentBuilders));
        }

        _mainBuildChainPatternTree = patternTree ?? throw new ArgumentNullException(nameof(patternTree));
        _auxPatternTree            = auxPatternTree;
        _parentBuilders            = parentBuilders;
        _buildChainList            = new List <UnitId>(4);
    }
    /// <summary>
    /// Overrides a previously registered <see cref="Treat{T}"/>. Mostly used in test environment to use mocks instead of real subsystems.
    /// </summary>
    public static TreatingTuner <T> TreatOverride <T>(this IBuildChainPattern pattern, object?tag = null)
    {
        if (pattern is null)
        {
            throw new ArgumentNullException(nameof(pattern));
        }

        var newPatternMatcher = new SkipTillUnit(new UnitPattern(typeof(T), tag), WeightOf.BuildChainPattern.TargetUnit + WeightOf.UnitPattern.ExactTypePattern);
        var oldPatternMatcher = pattern.Children.Single(_ => _.Equals(newPatternMatcher));

        pattern.Children.Remove(oldPatternMatcher);
        return(new TreatingTuner <T>(pattern.AddNode(newPatternMatcher)));
    }
    /// <summary>
    /// Adds a <paramref name="node" /> to the <see cref="IBuildChainPattern.Children"/> collection of <paramref name="parentNode"/>
    /// if the node does not already exist. Returns the new node, or the existing node if the node already exists.
    /// </summary>
    /// <remarks>Call it first and then fill returned <see cref="IBuildChainPattern" /> with build actions or perform other needed actions due to
    /// it can return other instance of <see cref="IBuildChainPattern"/> then <paramref name="node"/>.</remarks>
    public static T GetOrAddNode <T>(this IBuildChainPattern parentNode, T node) where T : IBuildChainPattern
    {
        if (parentNode is null)
        {
            throw new ArgumentNullException(nameof(parentNode));
        }
        if (node is null)
        {
            throw new ArgumentNullException(nameof(node));
        }

        if (parentNode.Children.Contains(node))
        {
            return((T)parentNode.Children.First(_ => _.Equals(node)));
        }

        parentNode.Children.Add(node);
        return(node);
    }
    /// <summary>
    /// Adds the <paramref name="node" /> into <paramref name="parentNode" />.
    /// </summary>
    /// <exception cref="ArmatureException">A node is already in the tree</exception>
    public static T AddNode <T>(this IBuildChainPattern parentNode, T node, string?exceptionMessage = null) where T : IBuildChainPattern
    {
        if (parentNode is null)
        {
            throw new ArgumentNullException(nameof(parentNode));
        }
        if (node is null)
        {
            throw new ArgumentNullException(nameof(node));
        }

        if (parentNode.Children.Contains(node))
        {
            throw new ArmatureException(exceptionMessage ?? $"Node '{node}' is already in the tree.")
                  .AddData($"{nameof(parentNode)}", parentNode)
                  .AddData($"{nameof(node)}", node);
        }

        parentNode.Children.Add(node);
        return(node);
    }
    /// <summary>
    /// Adds a <see cref="IBuildAction" /> for a "to be built" unit which is matched by the branch of the pattern tree represented by this node
    /// with its parents.
    /// </summary>
    /// <param name="node"></param>
    /// <param name="buildAction">A build action.</param>
    /// <param name="buildStage">A build stage in which the build action is executed.</param>
    /// <returns>Returns 'this' in order to use fluent syntax</returns>
    public static IBuildChainPattern UseBuildAction(this IBuildChainPattern node, IBuildAction buildAction, object buildStage)
    {
        if (node is null)
        {
            throw new ArgumentNullException(nameof(node));
        }
        if (buildAction is null)
        {
            throw new ArgumentNullException(nameof(buildAction));
        }
        if (buildStage is null)
        {
            throw new ArgumentNullException(nameof(buildStage));
        }

        var list = node.BuildActions.GetOrCreateValue(buildStage, () => new List <IBuildAction>());

        if (!list.Contains(buildAction))
        {
            list.Add(buildAction);
        }

        return(node);
    }
 public static TreatingTuner Treat(this IBuildChainPattern pattern, Type type, object?tag = null) => new RootTuner(pattern).Treat(type, tag);
 public static RootTuner Building <T>(this IBuildChainPattern pattern, object?tag = null) => new RootTuner(pattern).Building <T>(tag);
 public static RootTuner Building(this IBuildChainPattern pattern, Type type, object?tag = null) => new RootTuner(pattern).Building(type, tag);
 public static FinalTuner TreatAll(this IBuildChainPattern pattern) => new RootTuner(pattern).TreatAll();
 public static TreatingTuner <T> TreatInheritorsOf <T>(this IBuildChainPattern pattern, object?tag = null) => new RootTuner(pattern).TreatInheritorsOf <T>(tag);
 public static TreatingTuner TreatInheritorsOf(this IBuildChainPattern pattern, Type baseType, object?tag = null)
 => new RootTuner(pattern).TreatInheritorsOf(baseType, tag);
 public static TreatingOpenGenericTuner TreatOpenGeneric(this IBuildChainPattern pattern, Type openGenericType, object?tag = null)
 => new RootTuner(pattern).TreatOpenGeneric(openGenericType, tag);
示例#13
0
 public RootTuner(IBuildChainPattern parentNode) : base(parentNode)
 {
 }
示例#14
0
 public CreationTuner(IBuildChainPattern parentNode, Type type, object?tag) : base(parentNode)
 {
     Type = type ?? throw new ArgumentNullException(nameof(type));
     Tag  = tag;
 }
示例#15
0
 public TreatingTuner(IBuildChainPattern parentNode) : base(parentNode)
 {
 }
示例#16
0
 public FinalTuner(IBuildChainPattern parentNode) : base(parentNode)
 {
 }