前言
Revit 2021 发布了10个 Dynamo 新节点,刚好借此机会看一下 Dynamo 是如何开发的。
介绍
从官网说明,Revit Nodes for Dynamo 2.5,找到提示的 GitHub 入口,最终来到:https://github.com/DynamoDS/DynamoRevit/pull/2454。
从这个界面上看到,如果要提交新的 Node,至少需要以下几个部分:
- 节点本身的介绍
- 单元测试,自己写,并且通过测试
- 声明你的节点有百益而无一害
如何真正开发节点
如何真正开发节点?节点的实现 + 单元测试。
以新发的节点 Element.AreJoined
为例。
节点的实现
首先,你需要实现。这里是最简单的例子,因为原来已经有了 Element
类,所以只需要在它里面添加即可。
public 方法会直接被系统调用,并且变成一个节点,具体过程不必纠结,应该是通过 C# 的反射机制来完成的。实际上,其它的 ZeroTouch 节点也是通过反射来获得的。
// src/Libraries/RevitNodes/Elements/Element.cs
namespace Revit.Elements
{
//[SupressImportIntoVM]
public abstract class Element : IDisposable, IGraphicItem, IFormattable
{
// 其它代码
// ...
public bool AreJoined(Element otherElement)
{
return JoinGeometryUtils.AreElementsJoined(
Document,
this.InternalElement,
otherElement.InternalElement);
}
}
}
单元测试
有了节点的实现之后,必须写测试,以防以后功能坏了。
这里写了两个测试,CanCheckIfTwoElementsAreJoined
和 CanSuccessfullyCheckIfTwoElementsAreJoined
。
CanCheckIfTwoElementsAreJoined
Element 的测试已经有一些了,所以不用自己写一个测试类,只需要添加测试即可。不过如果想要自己添加也是可以的,继承 RevitSystemTestBase
。
测试模型,如果有的话可以加上,这样跑测试的时候希望打开这个模型, [TestModel(@".\Element\elementJoin.rvt")]
。
如果你的测试直接是一个脚本,那么也是可以的,打开 ViewModel.OpenCommand.Execute(testPath)
,运行 RunCurrentModel()
。
最后判断一下结果。"b29dc14336bc4c9382f9acc5036d632f"
可从脚本里面找到, test/System/Element/canCheckIfTwoElementsAreJoined.dyn
。
// test/Libraries/RevitIntegrationTests/ElementTests.cs
namespace RevitSystemTests
{
[TestFixture]
class ElementTests : RevitSystemTestBase
{
[Test]
[TestModel(@".\Element\elementJoin.rvt")]
public void CanCheckIfTwoElementsAreJoined()
{
// Arange
string samplePath = Path.Combine(workingDirectory, @".\Element\canCheckIfTwoElementsAreJoined.dyn");
string testPath = Path.GetFullPath(samplePath);
ViewModel.OpenCommand.Execute(testPath);
RunCurrentModel();
// Act - Get values of the two IsJoined nodes
// first one should return false as it is checking two elements that are not joined
// second one should return true as it test two joined elements
var isJoinedFalse = GetPreviewValue("b29dc14336bc4c9382f9acc5036d632f");
var isJoinedTrue = GetPreviewValue("b49a72f29d504acdb524ab0953623ea5");
// Assert
Assert.AreEqual(true, isJoinedTrue);
Assert.AreEqual(false, isJoinedFalse);
}
}
}
CanSuccessfullyCheckIfTwoElementsAreJoined
这个测试和前一个不同点在于,它不是打开一个 dyn
文件来运行,然后查看结果是否符合预期,而是直接用代码来判断。
它的逻辑是打开一个文件,.\Element\elementJoin.rvt
,选择,然后用代码,bool arejoined = element.AreJoined(otherElement)
,来判断结果。
// test/Libraries/RevitIntegrationTests/ElementTests.cs
namespace RevitSystemTests
{
[TestFixture]
class ElementTests : RevitSystemTestBase
{
[Test]
[TestModel(@".\Element\elementJoin.rvt")]
public void CanSuccessfullyCheckIfTwoElementsAreJoined()
{
var wall1 = ElementSelector.ByElementId(184176, true);
var wall2 = ElementSelector.ByElementId(207960, true);
var floor = ElementSelector.ByElementId(208259, true);
var beam1 = ElementSelector.ByElementId(208422, true);
var beam2 = ElementSelector.ByElementId(208572, true);
// Check if different kinds of elements are joined
// wall1 and wall2 are joined
AssertElementsAreJoined(wall1, wall2, true);
// wall1 and floor are joined
AssertElementsAreJoined(wall1, floor, true);
// wall2 and floor are not joined
AssertElementsAreJoined(wall2, floor, false);
// wall1 and beam1 are joined
AssertElementsAreJoined(wall1, beam1, true);
// wall2 and beam2 are not joined
AssertElementsAreJoined(wall2, beam2, false);
// beam1 and beam2 are joined
AssertElementsAreJoined(beam1, beam2, true);
// beam1 and floor are joined
AssertElementsAreJoined(beam1, floor, true);
}
private static void AssertElementsAreJoined(Element element, Element otherElement, bool expected)
{
bool arejoined = element.AreJoined(otherElement);
Assert.AreEqual(expected, arejoined);
}
}
}
总结
从这个提交里面看到,Dynamo 的开发流程还是很严格的,测试代码比实现代码多很多,还需要自己提供测试脚本和文件。