Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net4.8;net6.0;net8.0</TargetFrameworks>
<TargetFrameworks>net4.8;net8.0</TargetFrameworks>
<IsPackable>false</IsPackable>
<AppendTargetFrameworkToOutputPath>true</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.Xml.Serialization;
using Autodesk.PackageBuilder;

namespace Autodesk.PackageBuilder.Tests.Addin
{
/// <summary>
/// Provides extension methods for the <see cref="RevitAddInsBuilder"/> class.
/// </summary>
public static class RevitAddInsBuilderManifestSettingsExtensions
{
/// <summary>
/// Creates a new instance of <see cref="ManifestSettings"/> and adds it to the builder.
/// </summary>
/// <param name="builder">The <see cref="RevitAddInsBuilder"/> instance to extend.</param>
/// <returns>A new instance of <see cref="ManifestSettings"/>.</returns>
public static ManifestSettings CreateManifestSettings(this RevitAddInsBuilder builder)
{
var manifestSettings = new ManifestSettings();
builder.DataBuilder.CreateElement(nameof(ManifestSettings), manifestSettings);
return manifestSettings;
}

/// <summary>
/// Represents the manifest settings for Revit 2026.
/// </summary>
/// <remarks>
/// For more information, see:
/// https://help.autodesk.com/view/RVT/2026/ENU/?guid=Revit_API_Revit_API_Developers_Guide_Introduction_Add_In_Integration_Add_in_Dependency_Isolation_html
/// </remarks>
public class ManifestSettings
{
/// <summary>
/// Gets or sets a value indicating whether to use the Revit context.
/// </summary>
[XmlElement]
public bool UseRevitContext { get; set; }

/// <summary>
/// Gets or sets the name of the context.
/// </summary>
[XmlElement]
public string ContextName { get; set; }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using Autodesk.PackageBuilder.Tests.Utils;
using NUnit.Framework;
using System;
using System.Xml.Serialization;

namespace Autodesk.PackageBuilder.Tests.Addin
{
public class RevitAddInsBuilder_ManifestSettings_Tests
{
RevitAddInsBuilder builder;
[SetUp]
public void Setup()
{
builder = BuilderUtils.Build<RevitAddInsBuilder>();
}

[TestCase("ContextName")]
[TestCase("MyContext")]
public void Build_DataBuilder_ManifestSettings(string contextName)
{
var addIn = builder.AddIn.CreateEntry();
var manifestSettings = new ManifestSettings
{
UseRevitContext = true,
ContextName = contextName
};

builder.DataBuilder.CreateElement(nameof(ManifestSettings), manifestSettings);

builder.AssertElement(nameof(ManifestSettings.UseRevitContext), "true");
builder.AssertElement(nameof(ManifestSettings.ContextName), contextName);
}

[TestCase("ContextName")]
[TestCase("MyContext")]
public void Build_CreateManifestSettings(string contextName)
{
var addIn = builder.AddIn.CreateEntry();

var manifestSettings = builder.CreateManifestSettings();
manifestSettings.UseRevitContext = true;
manifestSettings.ContextName = contextName;

builder.AssertElement(nameof(ManifestSettings.UseRevitContext), "true");
builder.AssertElement(nameof(ManifestSettings.ContextName), contextName);
}

/// <summary>
/// ManifestSettings Revit 2026
/// </summary>
/// <remarks>
/// https://help.autodesk.com/view/RVT/2026/ENU/?guid=Revit_API_Revit_API_Developers_Guide_Introduction_Add_In_Integration_Add_in_Dependency_Isolation_html
/// </remarks>
public class ManifestSettings : ExtensibleData
{
[XmlElement]
public bool UseRevitContext { get; set; }
[XmlElement]
public string ContextName { get; set; }
}

[Test]
public void Build_RevitAddIns_DemoClass()
{
var builder = BuilderUtils.Build<DemoAddinBuilder>();
var content = builder.ToString();
Assert.AreEqual(DemoAddinBuilder.Expected, content, $"Expected: {DemoAddinBuilder.Expected}\nContent: {content}");
}

public class DemoAddinBuilder : RevitAddInsBuilder
{
public static string Expected => """"
<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
<AddIn Type="Application">
<Name>RevitAddin</Name>
<Assembly>RevitAddin.dll</Assembly>
<AddInId>11111111-2222-3333-4444-555555555555</AddInId>
<FullClassName>RevitAddin.App</FullClassName>
<VendorId>RevitAddin</VendorId>
<VendorDescription>RevitAddin</VendorDescription>
</AddIn>
<ManifestSettings>
<UseRevitContext>true</UseRevitContext>
<ContextName>ContextName</ContextName>
</ManifestSettings>
</RevitAddIns>
"""";
public DemoAddinBuilder()
{
AddIn.CreateEntry("Application")
.Name("RevitAddin")
.Assembly("RevitAddin.dll")
.AddInId("11111111-2222-3333-4444-555555555555")
.FullClassName("RevitAddin.App")
.VendorId("RevitAddin")
.VendorDescription("RevitAddin");

var manifestSettings = new ManifestSettings
{
UseRevitContext = true,
ContextName = "ContextName"
};

DataBuilder.CreateElement(nameof(ManifestSettings), manifestSettings);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net48;net6.0;net8.0</TargetFrameworks>
<TargetFrameworks>net48;net8.0</TargetFrameworks>
<IsPackable>false</IsPackable>
<LangVersion>latest</LangVersion>
</PropertyGroup>
Expand Down
55 changes: 40 additions & 15 deletions Autodesk.PackageBuilder/Builder/Abstractions/BuilderBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,47 @@
using System.Linq;
using System.Runtime.CompilerServices;
/// <summary>
/// BuilderBase
/// Provides a base class for builders that construct and manipulate data models of type <typeparamref name="TData"/>.
/// </summary>
/// <typeparam name="TBuilder"></typeparam>
/// <typeparam name="TData"></typeparam>
/// <typeparam name="TBuilder">The type of the builder class inheriting from this base class.</typeparam>
/// <typeparam name="TData">The type of the data model being built, which must inherit from <see cref="ExtensibleData"/> and have a parameterless constructor.</typeparam>
public abstract class BuilderBase<TBuilder, TData>
where TBuilder : class
where TData : ExtensibleData, new()
{
/// <summary>
/// Data
/// Gets or sets the data model being built.
/// </summary>
protected TData Data { get; set; }

/// <summary>
/// DataBuilder
/// Gets a <see cref="DataBuilderBase"/> instance for manipulating the underlying data model.
/// </summary>
public DataBuilderBase DataBuilder => new(Data);

/// <summary>
/// SetNewPropertyValue
/// Sets a new property value on the data model, creating the property if it does not already exist.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <param name="propertyName"></param>
/// <returns></returns>
/// <typeparam name="T">The type of the property to set, which must have a parameterless constructor.</typeparam>
/// <param name="value">The value to set for the property.</param>
/// <param name="propertyName">The name of the property to set. Defaults to the name of the calling member.</param>
/// <returns>The current builder instance for method chaining.</returns>
protected TBuilder SetNewPropertyValue<T>(object value, [CallerMemberName] string propertyName = null) where T : new()
{
return SetNewPropertyValue<T>(Data, propertyName, value);
}

/// <summary>
/// Retrieves the value of a property of the specified type from the given instance, creating the property if it does not already exist.
/// </summary>
/// <typeparam name="T">The type of the property to retrieve, which must have a parameterless constructor.</typeparam>
/// <param name="instance">The object instance from which to retrieve the property value.</param>
/// <returns>The value of the property.</returns>
/// <exception cref="NullReferenceException">Thrown if no property of the specified type exists on the instance.</exception>
internal T GetNewPropertyValue<T>(object instance) where T : new()
{
var type = instance.GetType();
var property = type.GetProperties().FirstOrDefault(e=>e.PropertyType == typeof(T)) ??
var property = type.GetProperties().FirstOrDefault(e => e.PropertyType == typeof(T)) ??
throw new NullReferenceException(
$"Property with type '{typeof(T)}' in class {type.Name} not found");

Expand All @@ -45,23 +54,39 @@ public abstract class BuilderBase<TBuilder, TData>
return (T)property.GetValue(instance);
}

/// <summary>
/// Sets a new property value on the specified instance, creating the property if it does not already exist.
/// </summary>
/// <typeparam name="T">The type of the property to set, which must have a parameterless constructor.</typeparam>
/// <param name="instance">The object instance on which to set the property value.</param>
/// <param name="propertyName">The name of the property to set.</param>
/// <param name="value">The value to set for the property.</param>
/// <returns>The current builder instance for method chaining.</returns>
private TBuilder SetNewPropertyValue<T>(object instance, string propertyName, object value) where T : new()
{
var data = GetNewPropertyValue<T>(instance);
return SetPropertyValue(data, propertyName, value);
}

/// <summary>
/// SetPropertyValue
/// Sets the value of a property on the data model.
/// </summary>
/// <param name="value"></param>
/// <param name="propertyName"></param>
/// <returns></returns>
/// <param name="value">The value to set for the property.</param>
/// <param name="propertyName">The name of the property to set. Defaults to the name of the calling member.</param>
/// <returns>The current builder instance for method chaining.</returns>
protected TBuilder SetPropertyValue(object value, [CallerMemberName] string propertyName = null)
{
return SetPropertyValue(Data, propertyName, value);
}

/// <summary>
/// Sets the value of a property on the specified instance.
/// </summary>
/// <param name="instance">The object instance on which to set the property value.</param>
/// <param name="propertyName">The name of the property to set.</param>
/// <param name="value">The value to set for the property.</param>
/// <returns>The current builder instance for method chaining.</returns>
/// <exception cref="NullReferenceException">Thrown if the specified property does not exist on the instance.</exception>
private TBuilder SetPropertyValue(object instance, string propertyName, object value)
{
var type = instance.GetType();
Expand Down
5 changes: 5 additions & 0 deletions Autodesk.PackageBuilder/Builder/RevitAddInsBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ public class RevitAddInsBuilder : IBuilder
/// </summary>
public IRevitAddInEntryBuilder AddIn => _addInEntryBuilder;

/// <summary>
/// Gets the data builder for configuring the <see cref="RevitAddIns"/> entry.
/// </summary>
public DataBuilderBase DataBuilder => _revitAddInsEntryBuilder.DataBuilder;

/// <summary>
/// Initializes a new instance of the <see cref="RevitAddInsBuilder"/> class.
/// </summary>
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [2.0.2] / 2025-10-31
### Features
- Support `DataBuilder` in `RevitAddInsBuilder`. (Fix: #21)
### Tests
- Add `RevitAddInsBuilder_ManifestSettings_Tests`.
- Remove `net6.0` target framework in tests.
- Add `RevitAddInsBuilderManifestSettingsExtensions` with extension to create `ManifestSettings`.

## [2.0.1] / 2025-07-15
### Features
- Support `Navisworks` extensible data.
Expand Down Expand Up @@ -100,6 +108,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- First Release

[vNext]: ../../compare/1.0.0...HEAD
[2.0.2]: ../../compare/2.0.1...2.0.2
[2.0.1]: ../../compare/2.0.0...2.0.1
[2.0.0]: ../../compare/1.0.6...1.2.0
[1.0.6]: ../../compare/1.0.5...1.0.6
Expand Down
6 changes: 3 additions & 3 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<Project>
<PropertyGroup>
<Version>2.0.1</Version>
</PropertyGroup>
<PropertyGroup>
<Version>2.0.2</Version>
</PropertyGroup>
</Project>