/// <summary> /// Clone <see cref="ILineKey"/> parts. /// </summary> /// <param name="line"></param> /// <param name="appender">(optional) appender to use for clone. If null uses the appender of <paramref name="line"/></param> /// <param name="parameterInfos">(optional) for checking which parameters are keys</param> /// <returns>clone of key parts</returns> /// <exception cref="LineException">If cloning failed.</exception> public static ILine CloneKey(this ILine line, ILineFactory appender = default, IParameterInfos parameterInfos = null) { if (appender == null) { appender = line.GetAppender(); } ILine result = null; if (parameterInfos == null) { appender.TryGetParameterInfos(out parameterInfos); } StructList16 <ILine> args = new StructList16 <ILine>(); for (ILine l = line; l != null; l = l.GetPreviousPart()) { if (l is ILineArgument || l is ILineArgumentEnumerable) { args.Add(l); } } for (int i = args.Count - 1; i >= 0; i--) { ILine l = args[i]; if (l is ILineParameterEnumerable lineParameters) { foreach (ILineParameter lineParameter in lineParameters) { if (lineParameter.IsCanonicalKey(parameterInfos)) { result = appender.Create <ILineCanonicalKey, string, string>(result, lineParameter.ParameterName, lineParameter.ParameterValue); } else if (lineParameter.IsNonCanonicalKey(parameterInfos)) { result = appender.Create <ILineNonCanonicalKey, string, string>(result, lineParameter.ParameterName, lineParameter.ParameterValue); } } } if (l is ILineParameter parameter) { if (parameter.IsCanonicalKey(parameterInfos)) { result = appender.Create <ILineCanonicalKey, string, string>(result, parameter.ParameterName, parameter.ParameterValue); } else if (parameter.IsNonCanonicalKey(parameterInfos)) { result = appender.Create <ILineNonCanonicalKey, string, string>(result, parameter.ParameterName, parameter.ParameterValue); } } } return(result ?? appender.Create <ILinePart>(null)); }