获取 Enterprise Architect 包节点的所有 child 个节点
Get all child nodes of an Enterprise Architect package node
我需要的
步骤 1
我需要在主根节点(= 包)下导出所有信息,无论节点类型如何。
步骤 2
使用该导出信息,我需要映射到第三方提供的 JSON 合同。
步骤 3
然后第三方可以使用我的 JSON 将信息从 EA 导入他们的系统。
我有什么
第 1 步已完成,我在我的目标位置有一个基于文件的数据转储,如下所示:
基本上这是一个静态 html 网站,它通过在 tree-view 中显示信息来对应 EA 结构,类似于您在 EA 中看到的方式。
我能做什么
正在浏览 EARoot 文件夹并读取其中 html 文件中提供的所有信息。
在我的例子中,EARoot 包含三个子文件夹:
- EA1
- EA2
- EA3
EA1 子文件夹包含
- EA1
- EA2
- EA1.html
- EA2.html
- EA3.html
html 文件包含我需要的信息,可以以有意义的方式解释数据。
赶上
EA 中没有直接 link 文件和实际节点结构。我可以根据可用数据做出假设,该假设在大多数情况下都有效,但它需要可靠且始终有效。
我可以在每个 html 文件中找到一个正确的 UUID,所以这将是 link 结构的一种方式,但是要找到这个结构,我需要能够获得一个节点的所有 children 的 UUIDS 并递归地遍历树。
我尝试了以下方法:
public Package GetRootPackage()
{
using (var repo = EnterpriseArchitect.Repository.Open(_connectionString))
{
return repo.GetPackage(this.RootPackageName);
}
}
EnterpriseArchitect.Repository 是 EA.Repository 之上的包装器,使其成为 IDisposable 以实现更好的连接管理。
使用上面定义的GetRootPackage方法,我可以连接并加载我想要的节点:
var root = MyBuilder.ConnectTo(myConnectionString)
.RootPackage(rootNodeName)
.GetRootPackage();
我认为我可以像这样获取它的 children:
var children = root.Packages;
但后来我得到了这个讨厌的错误:
System.Runtime.InteropServices.COMException HResult=0x80010105
Message=The server threw an exception. (Exception from HRESULT:
0x80010105 (RPC_E_SERVERFAULT)) Source=my.console
StackTrace: at EA.IDualPackage.get_Elements() at
my.console.Program.Main(String[] args) in
C:\Repos\my.console\Program.cs:line 29
我检查了事件查看器以获取更多信息并发现(仅)这个:
Faulting application name: EA.exe, version: 14.1.0.1427, time stamp: 0x5b9718a5
Faulting module name: EA.exe, version: 14.1.0.1427, time stamp: 0x5b9718a5
Exception code: 0xc0000005
Fault offset: 0x0049ffc4
Faulting process id: 0x2eac
Faulting application start time: 0x01d56eb6d931a965
Faulting application path: C:\Program Files (x86)\Sparx Systems\EA\EA.exe
Faulting module path: C:\Program Files (x86)\Sparx Systems\EA\EA.exe
Report Id: 223f8c89-c84a-45c6-9100-82af8e94643a
Faulting package full name:
Faulting package-relative application ID:
问题
我发现的关于此 HResult=0x80010105
的内容似乎与 Excel 相关,所以我不确定这是否有意义。
我是来自控制台的 运行,因为我知道 interop.EA
应该被认为是 not-threadsafe。
What can I do to avoid this issue and get the child packages?
导致问题的是 EA.Repository
之上的 IDisposable
包装器。如果我直接调用回购协议(使用 try catch finally
而不是 IDisposable
),我能够获得子节点。
防御性编程就这么多了...
我用的不是包装纸:
public class Repository : IDisposable
{
private EA.Repository _repo;
protected Repository(string connectionString)
{
_repo = new EA.Repository();
_repo.OpenFile(connectionString);
}
...
public void Dispose()
{
_repo.CloseFile();
_repo = null;
}
}
我现在直接使用 EA repo 获取(根)包信息:
public Package GetRootPackage()
{
var repo = new EA.Repository();
try
{
repo.OpenFile(_connectionString);
var pkg = (EA.Package)repo.Models.GetByName(this.RootPackageName);
if (pkg is null)
throw new ApplicationException($"Package \"{this.RootPackageName}\" not found.");
return pkg;
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
finally
{
Console.WriteLine("Closing repository...");
repo.CloseFile();
}
}
通过这个我可以做到:
var root = MyBuilder.ConnectTo(myConnectionString)
.RootPackage(rootNodeName)
.GetRootPackage();
foreach (var item in root.Packages)
{
var child = (IDualPackage)item;
var guid = child.PackageGUID;
}
并且 guid
变量包含正确的 PackageGUID
。
我需要的
步骤 1
我需要在主根节点(= 包)下导出所有信息,无论节点类型如何。
步骤 2
使用该导出信息,我需要映射到第三方提供的 JSON 合同。
步骤 3
然后第三方可以使用我的 JSON 将信息从 EA 导入他们的系统。
我有什么
第 1 步已完成,我在我的目标位置有一个基于文件的数据转储,如下所示:
基本上这是一个静态 html 网站,它通过在 tree-view 中显示信息来对应 EA 结构,类似于您在 EA 中看到的方式。
我能做什么
正在浏览 EARoot 文件夹并读取其中 html 文件中提供的所有信息。
在我的例子中,EARoot 包含三个子文件夹:
- EA1
- EA2
- EA3
EA1 子文件夹包含
- EA1
- EA2
- EA1.html
- EA2.html
- EA3.html
html 文件包含我需要的信息,可以以有意义的方式解释数据。
赶上
EA 中没有直接 link 文件和实际节点结构。我可以根据可用数据做出假设,该假设在大多数情况下都有效,但它需要可靠且始终有效。
我可以在每个 html 文件中找到一个正确的 UUID,所以这将是 link 结构的一种方式,但是要找到这个结构,我需要能够获得一个节点的所有 children 的 UUIDS 并递归地遍历树。
我尝试了以下方法:
public Package GetRootPackage()
{
using (var repo = EnterpriseArchitect.Repository.Open(_connectionString))
{
return repo.GetPackage(this.RootPackageName);
}
}
EnterpriseArchitect.Repository 是 EA.Repository 之上的包装器,使其成为 IDisposable 以实现更好的连接管理。
使用上面定义的GetRootPackage方法,我可以连接并加载我想要的节点:
var root = MyBuilder.ConnectTo(myConnectionString)
.RootPackage(rootNodeName)
.GetRootPackage();
我认为我可以像这样获取它的 children:
var children = root.Packages;
但后来我得到了这个讨厌的错误:
System.Runtime.InteropServices.COMException HResult=0x80010105
Message=The server threw an exception. (Exception from HRESULT: 0x80010105 (RPC_E_SERVERFAULT)) Source=my.console
StackTrace: at EA.IDualPackage.get_Elements() at my.console.Program.Main(String[] args) in C:\Repos\my.console\Program.cs:line 29
我检查了事件查看器以获取更多信息并发现(仅)这个:
Faulting application name: EA.exe, version: 14.1.0.1427, time stamp: 0x5b9718a5
Faulting module name: EA.exe, version: 14.1.0.1427, time stamp: 0x5b9718a5
Exception code: 0xc0000005
Fault offset: 0x0049ffc4
Faulting process id: 0x2eac
Faulting application start time: 0x01d56eb6d931a965
Faulting application path: C:\Program Files (x86)\Sparx Systems\EA\EA.exe
Faulting module path: C:\Program Files (x86)\Sparx Systems\EA\EA.exe
Report Id: 223f8c89-c84a-45c6-9100-82af8e94643a
Faulting package full name:
Faulting package-relative application ID:
问题
我发现的关于此 HResult=0x80010105
的内容似乎与 Excel 相关,所以我不确定这是否有意义。
我是来自控制台的 运行,因为我知道 interop.EA
应该被认为是 not-threadsafe。
What can I do to avoid this issue and get the child packages?
导致问题的是 EA.Repository
之上的 IDisposable
包装器。如果我直接调用回购协议(使用 try catch finally
而不是 IDisposable
),我能够获得子节点。
防御性编程就这么多了...
我用的不是包装纸:
public class Repository : IDisposable
{
private EA.Repository _repo;
protected Repository(string connectionString)
{
_repo = new EA.Repository();
_repo.OpenFile(connectionString);
}
...
public void Dispose()
{
_repo.CloseFile();
_repo = null;
}
}
我现在直接使用 EA repo 获取(根)包信息:
public Package GetRootPackage()
{
var repo = new EA.Repository();
try
{
repo.OpenFile(_connectionString);
var pkg = (EA.Package)repo.Models.GetByName(this.RootPackageName);
if (pkg is null)
throw new ApplicationException($"Package \"{this.RootPackageName}\" not found.");
return pkg;
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
finally
{
Console.WriteLine("Closing repository...");
repo.CloseFile();
}
}
通过这个我可以做到:
var root = MyBuilder.ConnectTo(myConnectionString)
.RootPackage(rootNodeName)
.GetRootPackage();
foreach (var item in root.Packages)
{
var child = (IDualPackage)item;
var guid = child.PackageGUID;
}
并且 guid
变量包含正确的 PackageGUID
。