Tận dụng `ForgeTypeId` để phát triển Add-in thông minh hơn
- Vấn đề với BuiltInParameter và BuiltInCategory truyền thống
- ForgeTypeId: Tiêu chuẩn mới cho định danh dữ liệu
- Cách sử dụng ForgeTypeId trong Revit API
- Lợi ích khi chuyển sang sử dụng ForgeTypeId
- Phụ thuộc phiên bản (Version-dependent): Các giá trị
enumnày có thể thay đổi hoặc có thêm thành phần mới qua các phiên bản Revit, đôi khi gây ra lỗi tương thích ngược. - Không linh hoạt: Chúng chỉ bao gồm các tham số và hạng mục dựng sẵn, không thể đại diện cho các tham số chia sẻ (Shared Parameters) hoặc các hạng mục tùy chỉnh.
- Hạn chế trong môi trường đa nền tảng: Khi Autodesk hướng tới một nền tảng dữ liệu chung (Forge), việc sử dụng các ID nội bộ của Revit không phải lúc nào cũng tối ưu cho việc trao đổi dữ liệu xuyên ứng dụng.
- Chuỗi định danh độc nhất (Unique String Identifier):
ForgeTypeIdsử dụng một chuỗi định danh duy nhất (ví dụ:autodesk.revit.parameter:WALL_HEIGHT) thay vì các giá trị số nguyên nhưElementIdhoặcenum. Chuỗi này được thiết kế để ổn định và không thay đổi giữa các phiên bản Revit. - Độc lập với phiên bản: Điều này là lợi ích lớn nhất. Một
ForgeTypeIdcho "chiều cao tường" sẽ giống nhau trên Revit 2021, 2022, 2023 và các phiên bản sau này. - Hỗ trợ đa dạng:
ForgeTypeIdđược sử dụng để định danh:- Đơn vị (Units):
UnitTypeId(ví dụ:UnitTypeId.Meters,UnitTypeId.Feet). - Loại tham số (Parameter Types):
SpecTypeId(ví dụ:SpecTypeId.Length,SpecTypeId.Area). - Tham số (Parameters):
BuiltInParameter(nhưBuiltInParameter.WALL_HEIGHT_PARAMđược ánh xạ sangautodesk.revit.parameter:WALL_HEIGHT). - Hạng mục (Categories):
BuiltInCategory(nhưBuiltInCategory.OST_Wallsđược ánh xạ sangautodesk.revit.category:walls). - Và nhiều loại định danh khác.
- Đơn vị (Units):
- Tương thích với Forge: Tên gọi
ForgeTypeIdngụ ý sự tích hợp chặt chẽ với Autodesk Forge, một nền tảng cho phép truy cập và làm việc với dữ liệu thiết kế trên đám mây. Điều này mở ra cánh cửa cho việc trao đổi dữ liệu BIM xuyên suốt các ứng dụng của Autodesk và bên thứ ba. - Tính tương thích tương lai: Add-in của bạn sẽ ít bị ảnh hưởng bởi những thay đổi nội bộ của Revit API trong các phiên bản sau. Một
ForgeTypeIdđã được định nghĩa sẽ ổn định hơn nhiều so với các giá trịenumcũ. - Tích hợp tốt hơn với Forge: Nếu bạn có kế hoạch phát triển các giải pháp tích hợp với Autodesk Forge (ví dụ: hiển thị dữ liệu Revit trên web, phân tích dữ liệu trên đám mây),
ForgeTypeIdsẽ tạo ra sự nhất quán về định danh dữ liệu. - Code rõ ràng hơn (trong một số trường hợp): Mặc dù chuỗi định danh có thể dài hơn, nhưng chúng thường mang tính mô tả cao hơn so với các giá trị số nguyên khó hiểu.
- Mở rộng khả năng:
ForgeTypeIdlà nền tảng cho các tính năng API mới liên quan đến quản lý dữ liệu và tương tác xuyên ứng dụng.
Trong các phiên bản Revit API gần đây (đặc biệt là từ Revit 2021 trở đi), Autodesk đã giới thiệu một thay đổi quan trọng và mang tính chiến lược: sự ra đời của ForgeTypeId. Đây không chỉ là một thay đổi về tên gọi hay kiểu dữ liệu, mà là một bước tiến lớn nhằm chuẩn hóa và hiện đại hóa cách chúng ta tương tác với dữ liệu trong Revit và cả hệ sinh thái Autodesk Forge. Nếu bạn vẫn đang sử dụng các BuiltInParameter hay BuiltInCategory cũ, đã đến lúc tìm hiểu về ForgeTypeId để tối ưu hóa Add-in của mình.
Vấn đề với BuiltInParameter và BuiltInCategory truyền thống
Trong nhiều năm, các lập trình viên Revit API đã quen thuộc với việc sử dụng BuiltInParameter và BuiltInCategory (các enum trong Revit API) để xác định các tham số và hạng mục dựng sẵn của Revit. Mặc dù tiện lợi, chúng có một số hạn chế đáng kể:
ForgeTypeId: Tiêu chuẩn mới cho định danh dữ liệu
ForgeTypeId là một kiểu dữ liệu mới được thiết kế để khắc phục những hạn chế trên. Nó cung cấp một cơ chế định danh độc lập với phiên bản và linh hoạt hơn cho các loại dữ liệu, đơn vị, tham số, và các đối tượng khác trong Revit và hệ sinh thái Forge rộng lớn hơn.
Các đặc điểm chính của ForgeTypeId:
Cách sử dụng ForgeTypeId trong Revit API
Từ Revit 2021 trở đi, nhiều phương thức API đã được quá tải (overload) để chấp nhận ForgeTypeId thay vì các ElementId hoặc enum truyền thống.
Chuyển đổi từ/sang ForgeTypeId
Bạn có thể chuyển đổi giữa BuiltInParameter/BuiltInCategory và ForgeTypeId bằng các phương thức của lớp ParameterUtils và Category.
// Đối với BuiltInParameter:
// Chuyển từ BuiltInParameter sang ForgeTypeId
ForgeTypeId wallHeightParamTypeId = ParameterUtils.Get
BuiltInParameterId(BuiltInParameter.WALL_HEIGHT_PARAM);
// Chuyển từ ForgeTypeId sang BuiltInParameter (cẩn thận: có thể ném ngoại lệ nếu không có ánh xạ)
BuiltInParameter biParam = ParameterUtils.GetBuiltInParameter(wallHeightParamTypeId);
// Đối với BuiltInCategory:
// Chuyển từ BuiltInCategory sang ForgeTypeId
ForgeTypeId wallCategoryTypeId = Category.Get
BuiltInCategoryTypeId(BuiltInCategory.OST_Walls);
// Chuyển từ ForgeTypeId sang BuiltInCategory
BuiltInCategory biCategory = Category.GetBuiltInCategory(wallCategoryTypeId);
Truy xuất giá trị tham số bằng ForgeTypeId
Bạn có thể sử dụng ForgeTypeId để truy xuất giá trị của tham số một cách rõ ràng hơn và độc lập với phiên bản.
// Giả sử có một đối tượng tường (wallElement)
Element wallElement = ...; // Lấy từ FilteredElementCollector hoặc cách khác
// Truy xuất tham số chiều cao tường bằng ForgeTypeId
Parameter wallHeightParameter = wallElement.get_Parameter(
ParameterUtils.GetBuiltInParameterId(BuiltInParameter.WALL_HEIGHT_PARAM));
if (wallHeightParameter != null)
{
// Lấy giá trị theo đơn vị hiển thị mặc định của dự án
double heightValue = wallHeightParameter.AsDouble();
TaskDialog.Show("Wall Height", $"Chiều cao tường: {heightValue} feet (nếu đơn vị dự án là feet).");
// Hoặc lấy giá trị theo một đơn vị cụ thể bằng ForgeTypeId cho đơn vị
// Trong Revit 2022+, có các phương thức GetAs... và Set... có thể nhận UnitTypeId
// double heightInMeters = wallHeightParameter.AsDouble(UnitTypeId.Meters); // Ví dụ (phụ thuộc phiên bản API)
}
Lọc phần tử bằng ForgeTypeId
Các phương thức của FilteredElementCollector cũng được quá tải để chấp nhận ForgeTypeId.
// Lấy tất cả các tường sử dụng ForgeTypeId
FilteredElementCollector collector = new FilteredElementCollector(doc);
ICollection<Element> walls = collector.OfCategory(Category.GetBuiltInCategoryTypeId(BuiltInCategory.OST_Walls))
.ToElements();
// Lọc theo SpecTypeId cho các tham số (nếu có API hỗ trợ trực tiếp)
// Ví dụ: Tìm tất cả các tham số có SpecTypeId là Length
// Đây là ví dụ khái quát, việc lọc Parameter theo SpecTypeId thường yêu cầu cấu hình FilterRule phức tạp hơn.
ForgeTypeId lengthSpec = SpecTypeId.Length;
// Một ví dụ phức tạp hơn khi dùng ParameterFilter với SpecTypeId
// ParameterFilterElement.CreateParameterFilterElement(doc, "MyLengthFilter", new List<ElementId>(), new ParameterFilterRuleFactory.CreateHasValueRule(lengthSpec));
Định danh các đơn vị với UnitTypeId và SpecTypeId
UnitTypeId và SpecTypeId là một phần của hệ thống ForgeTypeId giúp bạn làm việc với các đơn vị và loại tham số một cách nhất quán.
// Lấy UnitTypeId cho mét
ForgeTypeId metersTypeId = UnitTypeId.Meters;
// Lấy SpecTypeId cho chiều dài
ForgeTypeId lengthSpecTypeId = SpecTypeId.Length;
// Chuyển đổi giữa các đơn vị (sử dụng UnitUtils)
double lengthInFeet = 10.0; // Giả sử 10 feet
double lengthInMm = UnitUtils.Convert(lengthInFeet, UnitTypeId.Feet, UnitTypeId.Millimeters);
TaskDialog.Show("Unit Conversion", $"10 feet = {lengthInMm} mm");
Lợi ích khi chuyển sang sử dụng ForgeTypeId
Bạn đã bắt đầu chuyển đổi sang ForgeTypeId trong các dự án của mình chưa? Bạn thấy những lợi ích hay thách thức nào khi sử dụng nó? Hãy chia sẻ kinh nghiệm của bạn ở phần bình luận nhé!