646 lines
23 KiB
C#
646 lines
23 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Xml;
|
||
using System.Xml.Serialization;
|
||
using System.Text;
|
||
using System.Linq;
|
||
|
||
using Autodesk.Navisworks.Api;
|
||
|
||
namespace NavisworksTransport
|
||
{
|
||
/// <summary>
|
||
/// 路径数据管理器
|
||
/// 负责路径数据的导入导出、持久化存储和DELMIA格式兼容
|
||
/// </summary>
|
||
public class PathDataManager
|
||
{
|
||
private const string DEFAULT_EXPORT_FOLDER = "PathPlanningExports";
|
||
private const string DEFAULT_FILE_EXTENSION = ".xml";
|
||
private const string JSON_FILE_EXTENSION = ".json";
|
||
|
||
// DELMIA兼容格式配置
|
||
private readonly string _delmiaNamespace = "http://www.3ds.com/delmia/pathplanning";
|
||
private readonly string _delmiaVersion = "1.0";
|
||
|
||
/// <summary>
|
||
/// 导出路径到XML文件(DELMIA兼容格式)
|
||
/// </summary>
|
||
/// <param name="routes">路径集合</param>
|
||
/// <param name="filePath">文件路径</param>
|
||
/// <param name="exportSettings">导出设置</param>
|
||
/// <returns>是否成功</returns>
|
||
public bool ExportToXml(List<PathRoute> routes, string filePath, ExportSettings exportSettings = null)
|
||
{
|
||
if (routes == null || routes.Count == 0)
|
||
{
|
||
throw new ArgumentException("路径集合不能为空");
|
||
}
|
||
|
||
try
|
||
{
|
||
// 确保导出目录存在
|
||
var directory = Path.GetDirectoryName(filePath);
|
||
if (!Directory.Exists(directory))
|
||
{
|
||
Directory.CreateDirectory(directory);
|
||
}
|
||
|
||
// 创建XML文档
|
||
var xmlDoc = new XmlDocument();
|
||
var declaration = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", null);
|
||
xmlDoc.AppendChild(declaration);
|
||
|
||
// 创建根元素
|
||
var rootElement = xmlDoc.CreateElement("PathPlanningData", _delmiaNamespace);
|
||
rootElement.SetAttribute("version", _delmiaVersion);
|
||
rootElement.SetAttribute("generator", "NavisworksTransport");
|
||
rootElement.SetAttribute("timestamp", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss"));
|
||
xmlDoc.AppendChild(rootElement);
|
||
|
||
// 添加项目信息
|
||
var projectInfo = CreateProjectInfoElement(xmlDoc, exportSettings);
|
||
rootElement.AppendChild(projectInfo);
|
||
|
||
// 添加路径数据
|
||
var routesElement = xmlDoc.CreateElement("Routes", _delmiaNamespace);
|
||
rootElement.AppendChild(routesElement);
|
||
|
||
foreach (var route in routes)
|
||
{
|
||
if (route.IsValid())
|
||
{
|
||
var routeElement = CreateRouteElement(xmlDoc, route, exportSettings);
|
||
routesElement.AppendChild(routeElement);
|
||
}
|
||
}
|
||
|
||
// 保存文件
|
||
using (var writer = new XmlTextWriter(filePath, Encoding.UTF8))
|
||
{
|
||
writer.Formatting = Formatting.Indented;
|
||
writer.Indentation = 2;
|
||
xmlDoc.WriteTo(writer);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"导出XML文件失败: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从XML文件导入路径
|
||
/// </summary>
|
||
/// <param name="filePath">文件路径</param>
|
||
/// <returns>路径集合</returns>
|
||
public List<PathRoute> ImportFromXml(string filePath)
|
||
{
|
||
var routes = new List<PathRoute>();
|
||
|
||
if (!File.Exists(filePath))
|
||
{
|
||
throw new FileNotFoundException($"文件不存在: {filePath}");
|
||
}
|
||
|
||
try
|
||
{
|
||
var xmlDoc = new XmlDocument();
|
||
xmlDoc.Load(filePath);
|
||
|
||
// 验证根元素
|
||
var rootElement = xmlDoc.DocumentElement;
|
||
if (rootElement?.Name != "PathPlanningData")
|
||
{
|
||
throw new InvalidOperationException("无效的路径规划数据文件格式");
|
||
}
|
||
|
||
// 读取路径数据
|
||
var routesElement = rootElement.SelectSingleNode("*[local-name()='Routes']");
|
||
if (routesElement != null)
|
||
{
|
||
foreach (XmlNode routeNode in routesElement.ChildNodes)
|
||
{
|
||
if (routeNode.NodeType == XmlNodeType.Element)
|
||
{
|
||
var route = ParseRouteElement(routeNode);
|
||
if (route != null && route.IsValid())
|
||
{
|
||
routes.Add(route);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return routes;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"导入XML文件失败: {ex.Message}");
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 导出路径到JSON文件(简化实现)
|
||
/// </summary>
|
||
/// <param name="routes">路径集合</param>
|
||
/// <param name="filePath">文件路径</param>
|
||
/// <param name="exportSettings">导出设置</param>
|
||
/// <returns>是否成功</returns>
|
||
public bool ExportToJson(List<PathRoute> routes, string filePath, ExportSettings exportSettings = null)
|
||
{
|
||
// JSON功能暂未实现,建议使用XML格式
|
||
return ExportToXml(routes, filePath.Replace(".json", ".xml"), exportSettings);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从JSON文件导入路径(简化实现)
|
||
/// </summary>
|
||
/// <param name="filePath">文件路径</param>
|
||
/// <returns>路径集合</returns>
|
||
public List<PathRoute> ImportFromJson(string filePath)
|
||
{
|
||
// JSON功能暂未实现,建议使用XML格式
|
||
return ImportFromXml(filePath.Replace(".json", ".xml"));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存路径到Navisworks文件
|
||
/// </summary>
|
||
/// <param name="routes">路径集合</param>
|
||
/// <param name="filePath">文件路径</param>
|
||
/// <returns>是否成功</returns>
|
||
public bool SaveToNavisworksFile(List<PathRoute> routes, string filePath)
|
||
{
|
||
try
|
||
{
|
||
// 创建临时属性来存储路径数据
|
||
var document = Application.ActiveDocument;
|
||
if (document == null)
|
||
{
|
||
throw new InvalidOperationException("没有活动的Navisworks文档");
|
||
}
|
||
|
||
// 简化实现:跳过路径数据序列化
|
||
|
||
// 这里可以将路径数据保存为自定义属性
|
||
// 由于Navisworks API的限制,这里是简化实现
|
||
// 实际应用中可能需要使用COM API来添加自定义属性
|
||
|
||
// 保存当前文档
|
||
if (Path.GetExtension(filePath).ToLower() == ".nwd")
|
||
{
|
||
document.PublishFile(filePath, new PublishProperties());
|
||
}
|
||
else
|
||
{
|
||
document.SaveFile(filePath);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"保存到Navisworks文件失败: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从Navisworks文件加载路径
|
||
/// </summary>
|
||
/// <param name="filePath">文件路径</param>
|
||
/// <returns>路径集合</returns>
|
||
public List<PathRoute> LoadFromNavisworksFile(string filePath)
|
||
{
|
||
var routes = new List<PathRoute>();
|
||
|
||
try
|
||
{
|
||
// 这里应该从Navisworks文件的自定义属性中读取路径数据
|
||
// 由于API限制,这里是简化实现
|
||
// 实际应用中需要使用COM API来读取自定义属性
|
||
|
||
return routes;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"从Navisworks文件加载失败: {ex.Message}");
|
||
return routes;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 导出DELMIA兼容格式
|
||
/// </summary>
|
||
/// <param name="routes">路径集合</param>
|
||
/// <param name="filePath">文件路径</param>
|
||
/// <param name="exportSettings">导出设置</param>
|
||
/// <returns>是否成功</returns>
|
||
public bool ExportDelmiaFormat(List<PathRoute> routes, string filePath, ExportSettings exportSettings = null)
|
||
{
|
||
try
|
||
{
|
||
// 确保导出目录存在
|
||
var directory = Path.GetDirectoryName(filePath);
|
||
if (!Directory.Exists(directory))
|
||
{
|
||
Directory.CreateDirectory(directory);
|
||
}
|
||
|
||
var xmlDoc = new XmlDocument();
|
||
var declaration = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", null);
|
||
xmlDoc.AppendChild(declaration);
|
||
|
||
// 创建DELMIA格式的根元素
|
||
var rootElement = xmlDoc.CreateElement("DELMIA_PathPlanning", _delmiaNamespace);
|
||
rootElement.SetAttribute("version", _delmiaVersion);
|
||
rootElement.SetAttribute("units", exportSettings?.Units ?? "meters");
|
||
xmlDoc.AppendChild(rootElement);
|
||
|
||
// 添加任务信息
|
||
var taskInfo = xmlDoc.CreateElement("TaskInfo", _delmiaNamespace);
|
||
taskInfo.SetAttribute("name", exportSettings?.ProjectName ?? "物流路径规划");
|
||
taskInfo.SetAttribute("description", exportSettings?.Description ?? "从Navisworks导出的路径规划任务");
|
||
taskInfo.SetAttribute("created", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss"));
|
||
rootElement.AppendChild(taskInfo);
|
||
|
||
// 添加路径集合
|
||
var pathsElement = xmlDoc.CreateElement("Paths", _delmiaNamespace);
|
||
rootElement.AppendChild(pathsElement);
|
||
|
||
foreach (var route in routes.Where(r => r.IsValid()))
|
||
{
|
||
var pathElement = CreateDelmiaPathElement(xmlDoc, route, exportSettings);
|
||
pathsElement.AppendChild(pathElement);
|
||
}
|
||
|
||
// 保存文件
|
||
using (var writer = new XmlTextWriter(filePath, Encoding.UTF8))
|
||
{
|
||
writer.Formatting = Formatting.Indented;
|
||
writer.Indentation = 2;
|
||
xmlDoc.WriteTo(writer);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"导出DELMIA格式失败: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取默认导出路径
|
||
/// </summary>
|
||
/// <param name="fileName">文件名</param>
|
||
/// <param name="format">格式</param>
|
||
/// <returns>完整路径</returns>
|
||
public string GetDefaultExportPath(string fileName, ExportFormat format)
|
||
{
|
||
var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
|
||
var exportPath = Path.Combine(documentsPath, DEFAULT_EXPORT_FOLDER);
|
||
|
||
if (!Directory.Exists(exportPath))
|
||
{
|
||
Directory.CreateDirectory(exportPath);
|
||
}
|
||
|
||
var extension = format == ExportFormat.Json ? JSON_FILE_EXTENSION : DEFAULT_FILE_EXTENSION;
|
||
return Path.Combine(exportPath, fileName + extension);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证导出文件
|
||
/// </summary>
|
||
/// <param name="filePath">文件路径</param>
|
||
/// <param name="format">格式</param>
|
||
/// <returns>验证结果</returns>
|
||
public ValidationResult ValidateExportFile(string filePath, ExportFormat format)
|
||
{
|
||
var result = new ValidationResult();
|
||
|
||
try
|
||
{
|
||
if (!File.Exists(filePath))
|
||
{
|
||
result.IsValid = false;
|
||
result.Errors.Add("文件不存在");
|
||
return result;
|
||
}
|
||
|
||
if (format == ExportFormat.Xml)
|
||
{
|
||
// 验证XML格式
|
||
var xmlDoc = new XmlDocument();
|
||
xmlDoc.Load(filePath);
|
||
|
||
if (xmlDoc.DocumentElement?.Name != "PathPlanningData" &&
|
||
xmlDoc.DocumentElement?.Name != "DELMIA_PathPlanning")
|
||
{
|
||
result.Warnings.Add("XML根元素格式可能不正确");
|
||
}
|
||
}
|
||
else if (format == ExportFormat.Json)
|
||
{
|
||
// JSON验证暂未实现
|
||
result.Warnings.Add("JSON格式验证暂未实现,建议使用XML格式");
|
||
}
|
||
|
||
result.IsValid = true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
result.IsValid = false;
|
||
result.Errors.Add($"文件验证失败: {ex.Message}");
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
#region 私有辅助方法
|
||
|
||
/// <summary>
|
||
/// 创建项目信息元素
|
||
/// </summary>
|
||
private XmlElement CreateProjectInfoElement(XmlDocument xmlDoc, ExportSettings settings)
|
||
{
|
||
var projectInfo = xmlDoc.CreateElement("ProjectInfo", _delmiaNamespace);
|
||
projectInfo.SetAttribute("name", settings?.ProjectName ?? "NavisworksTransport路径规划");
|
||
projectInfo.SetAttribute("description", settings?.Description ?? "物流路径规划数据");
|
||
projectInfo.SetAttribute("units", settings?.Units ?? "meters");
|
||
projectInfo.SetAttribute("coordinateSystem", settings?.CoordinateSystem ?? "Global");
|
||
|
||
return projectInfo;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建路径元素
|
||
/// </summary>
|
||
private XmlElement CreateRouteElement(XmlDocument xmlDoc, PathRoute route, ExportSettings settings)
|
||
{
|
||
var routeElement = xmlDoc.CreateElement("Route", _delmiaNamespace);
|
||
routeElement.SetAttribute("id", route.Id);
|
||
routeElement.SetAttribute("name", route.Name);
|
||
routeElement.SetAttribute("description", route.Description ?? "");
|
||
routeElement.SetAttribute("totalLength", route.TotalLength.ToString("F3"));
|
||
routeElement.SetAttribute("created", route.CreatedTime.ToString("yyyy-MM-ddTHH:mm:ss"));
|
||
|
||
// 添加路径点
|
||
var pointsElement = xmlDoc.CreateElement("Points", _delmiaNamespace);
|
||
routeElement.AppendChild(pointsElement);
|
||
|
||
var sortedPoints = route.GetSortedPoints();
|
||
foreach (var point in sortedPoints)
|
||
{
|
||
var pointElement = xmlDoc.CreateElement("Point", _delmiaNamespace);
|
||
pointElement.SetAttribute("id", point.Id);
|
||
pointElement.SetAttribute("name", point.Name);
|
||
pointElement.SetAttribute("type", point.Type.ToString());
|
||
pointElement.SetAttribute("index", point.Index.ToString());
|
||
pointElement.SetAttribute("x", point.Position.X.ToString("F6"));
|
||
pointElement.SetAttribute("y", point.Position.Y.ToString("F6"));
|
||
pointElement.SetAttribute("z", point.Position.Z.ToString("F6"));
|
||
pointElement.SetAttribute("created", point.CreatedTime.ToString("yyyy-MM-ddTHH:mm:ss"));
|
||
|
||
pointsElement.AppendChild(pointElement);
|
||
}
|
||
|
||
return routeElement;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 解析路径元素
|
||
/// </summary>
|
||
private PathRoute ParseRouteElement(XmlNode routeNode)
|
||
{
|
||
try
|
||
{
|
||
var route = new PathRoute
|
||
{
|
||
Id = routeNode.Attributes?["id"]?.Value ?? Guid.NewGuid().ToString(),
|
||
Name = routeNode.Attributes?["name"]?.Value ?? "导入路径",
|
||
Description = routeNode.Attributes?["description"]?.Value ?? ""
|
||
};
|
||
|
||
// 解析创建时间
|
||
if (DateTime.TryParse(routeNode.Attributes?["created"]?.Value, out DateTime createdTime))
|
||
{
|
||
route.CreatedTime = createdTime;
|
||
}
|
||
|
||
// 解析路径点
|
||
var pointsNode = routeNode.SelectSingleNode("*[local-name()='Points']");
|
||
if (pointsNode != null)
|
||
{
|
||
foreach (XmlNode pointNode in pointsNode.ChildNodes)
|
||
{
|
||
if (pointNode.NodeType == XmlNodeType.Element)
|
||
{
|
||
var point = ParsePointElement(pointNode);
|
||
if (point != null)
|
||
{
|
||
route.AddPoint(point);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return route;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"解析路径元素失败: {ex.Message}");
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 解析路径点元素
|
||
/// </summary>
|
||
private PathPoint ParsePointElement(XmlNode pointNode)
|
||
{
|
||
try
|
||
{
|
||
var point = new PathPoint
|
||
{
|
||
Id = pointNode.Attributes?["id"]?.Value ?? Guid.NewGuid().ToString(),
|
||
Name = pointNode.Attributes?["name"]?.Value ?? ""
|
||
};
|
||
|
||
// 解析位置
|
||
if (double.TryParse(pointNode.Attributes?["x"]?.Value, out double x) &&
|
||
double.TryParse(pointNode.Attributes?["y"]?.Value, out double y) &&
|
||
double.TryParse(pointNode.Attributes?["z"]?.Value, out double z))
|
||
{
|
||
point.Position = new Point3D(x, y, z);
|
||
}
|
||
|
||
// 解析索引
|
||
if (int.TryParse(pointNode.Attributes?["index"]?.Value, out int index))
|
||
{
|
||
point.Index = index;
|
||
}
|
||
|
||
// 解析类型
|
||
if (Enum.TryParse<PathPointType>(pointNode.Attributes?["type"]?.Value, out PathPointType type))
|
||
{
|
||
point.Type = type;
|
||
}
|
||
|
||
// 解析创建时间
|
||
if (DateTime.TryParse(pointNode.Attributes?["created"]?.Value, out DateTime createdTime))
|
||
{
|
||
point.CreatedTime = createdTime;
|
||
}
|
||
|
||
return point;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
System.Diagnostics.Debug.WriteLine($"解析路径点元素失败: {ex.Message}");
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建DELMIA路径元素
|
||
/// </summary>
|
||
private XmlElement CreateDelmiaPathElement(XmlDocument xmlDoc, PathRoute route, ExportSettings settings)
|
||
{
|
||
var pathElement = xmlDoc.CreateElement("Path", _delmiaNamespace);
|
||
pathElement.SetAttribute("id", route.Id);
|
||
pathElement.SetAttribute("name", route.Name);
|
||
pathElement.SetAttribute("type", "Transportation");
|
||
pathElement.SetAttribute("length", route.TotalLength.ToString("F3"));
|
||
|
||
// 添加路径段
|
||
var segmentsElement = xmlDoc.CreateElement("Segments", _delmiaNamespace);
|
||
pathElement.AppendChild(segmentsElement);
|
||
|
||
var sortedPoints = route.GetSortedPoints();
|
||
for (int i = 0; i < sortedPoints.Count - 1; i++)
|
||
{
|
||
var segmentElement = xmlDoc.CreateElement("Segment", _delmiaNamespace);
|
||
segmentElement.SetAttribute("index", i.ToString());
|
||
|
||
// 起点
|
||
var startElement = xmlDoc.CreateElement("Start", _delmiaNamespace);
|
||
AddDelmiaPointData(xmlDoc, startElement, sortedPoints[i]);
|
||
segmentElement.AppendChild(startElement);
|
||
|
||
// 终点
|
||
var endElement = xmlDoc.CreateElement("End", _delmiaNamespace);
|
||
AddDelmiaPointData(xmlDoc, endElement, sortedPoints[i + 1]);
|
||
segmentElement.AppendChild(endElement);
|
||
|
||
segmentsElement.AppendChild(segmentElement);
|
||
}
|
||
|
||
return pathElement;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加DELMIA点数据
|
||
/// </summary>
|
||
private void AddDelmiaPointData(XmlDocument xmlDoc, XmlElement element, PathPoint point)
|
||
{
|
||
element.SetAttribute("x", point.Position.X.ToString("F6"));
|
||
element.SetAttribute("y", point.Position.Y.ToString("F6"));
|
||
element.SetAttribute("z", point.Position.Z.ToString("F6"));
|
||
element.SetAttribute("name", point.Name);
|
||
element.SetAttribute("type", point.Type.ToString());
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
|
||
/// <summary>
|
||
/// 导出格式枚举
|
||
/// </summary>
|
||
public enum ExportFormat
|
||
{
|
||
Xml,
|
||
Json,
|
||
Delmia,
|
||
Navisworks
|
||
}
|
||
|
||
/// <summary>
|
||
/// 导出设置
|
||
/// </summary>
|
||
public class ExportSettings
|
||
{
|
||
/// <summary>
|
||
/// 项目名称
|
||
/// </summary>
|
||
public string ProjectName { get; set; } = "NavisworksTransport路径规划";
|
||
|
||
/// <summary>
|
||
/// 项目描述
|
||
/// </summary>
|
||
public string Description { get; set; } = "物流路径规划数据";
|
||
|
||
/// <summary>
|
||
/// 单位
|
||
/// </summary>
|
||
public string Units { get; set; } = "meters";
|
||
|
||
/// <summary>
|
||
/// 坐标系
|
||
/// </summary>
|
||
public string CoordinateSystem { get; set; } = "Global";
|
||
|
||
/// <summary>
|
||
/// 是否包含时间戳
|
||
/// </summary>
|
||
public bool IncludeTimestamps { get; set; } = true;
|
||
|
||
/// <summary>
|
||
/// 是否包含元数据
|
||
/// </summary>
|
||
public bool IncludeMetadata { get; set; } = true;
|
||
|
||
/// <summary>
|
||
/// 精度(小数位数)
|
||
/// </summary>
|
||
public int Precision { get; set; } = 6;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证结果
|
||
/// </summary>
|
||
public class ValidationResult
|
||
{
|
||
/// <summary>
|
||
/// 是否有效
|
||
/// </summary>
|
||
public bool IsValid { get; set; } = true;
|
||
|
||
/// <summary>
|
||
/// 错误信息
|
||
/// </summary>
|
||
public List<string> Errors { get; set; } = new List<string>();
|
||
|
||
/// <summary>
|
||
/// 警告信息
|
||
/// </summary>
|
||
public List<string> Warnings { get; set; } = new List<string>();
|
||
|
||
/// <summary>
|
||
/// 获取所有消息
|
||
/// </summary>
|
||
/// <returns>消息集合</returns>
|
||
public IEnumerable<string> GetAllMessages()
|
||
{
|
||
return Errors.Concat(Warnings);
|
||
}
|
||
}
|
||
} |