├── Directory.Build.props
├── Build
├── .nuke
│ ├── parameters.json
│ └── build.schema.json
├── build.cmd
├── Build.cs
├── .editorconfig
├── Build.csproj
├── build.sh
└── build.ps1
├── RevitAddin.CommandLoader
├── Resources
│ ├── CommandLoader.ico
│ └── CommandLoader.tiff
├── Services
│ ├── CodeDom
│ │ ├── ICodeDomService.cs
│ │ ├── CodeProviderService.cs
│ │ ├── CodeDomService.cs
│ │ └── CodeAnalysisCodeDomService.cs
│ ├── CodeDomFactory.cs
│ ├── JsonService.cs
│ └── GistGithubUtils.cs
├── Revit
│ ├── InfoCenterUtils.cs
│ ├── Commands
│ │ ├── Command.cs
│ │ ├── CommandTestGist.cs
│ │ ├── CommandTestGistFiles.cs
│ │ └── CommandTest.cs
│ ├── App.cs
│ └── CodeSamples.cs
├── Views
│ ├── CompileView.xaml.cs
│ └── CompileView.xaml
├── Extensions
│ ├── AppName.cs
│ ├── AutodeskIconGeneratorUtils.cs
│ └── AttributeExtension.cs
├── ViewModels
│ └── CompileViewModel.cs
└── RevitAddin.CommandLoader.csproj
├── .github
└── workflows
│ └── Build.yml
├── RevitAddin.CommandLoader.Tests
├── CodeDom
│ ├── CodeDomTester.cs
│ └── CodeTester.cs
├── CodeDomTests.cs
├── GistGithubUtilsTests.cs
└── RevitAddin.CommandLoader.Tests.csproj
├── LICENSE
├── .gitattributes
├── CHANGELOG.md
├── RevitAddin.CommandLoader.sln
├── README.md
└── .gitignore
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | 1.2.0
4 |
5 |
--------------------------------------------------------------------------------
/Build/.nuke/parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./build.schema.json",
3 | "Solution": "../RevitAddin.CommandLoader.sln"
4 | }
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Resources/CommandLoader.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ricaun-io/RevitAddin.CommandLoader/HEAD/RevitAddin.CommandLoader/Resources/CommandLoader.ico
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Resources/CommandLoader.tiff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ricaun-io/RevitAddin.CommandLoader/HEAD/RevitAddin.CommandLoader/Resources/CommandLoader.tiff
--------------------------------------------------------------------------------
/Build/build.cmd:
--------------------------------------------------------------------------------
1 | :; set -eo pipefail
2 | :; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
3 | :; ${SCRIPT_DIR}/build.sh "$@"
4 | :; exit $?
5 |
6 | @ECHO OFF
7 | powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %*
8 |
--------------------------------------------------------------------------------
/Build/Build.cs:
--------------------------------------------------------------------------------
1 | using Nuke.Common;
2 | using Nuke.Common.Execution;
3 | using ricaun.Nuke;
4 | using ricaun.Nuke.Components;
5 |
6 | class Build : NukeBuild, IPublishRevit, ITest, IGitPreRelease
7 | {
8 | string IHazRevitPackageBuilder.Application => "Revit.App";
9 | public static int Main() => Execute(x => x.From().Build);
10 | }
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Services/CodeDom/ICodeDomService.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | namespace RevitAddin.CommandLoader.Services.CodeDom
4 | {
5 | public interface ICodeDomService
6 | {
7 | Assembly GenerateCode(params string[] sourceCode);
8 | public ICodeDomService SetDefines(params string[] defines);
9 |
10 | }
11 | }
--------------------------------------------------------------------------------
/Build/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cs]
2 | dotnet_style_qualification_for_field = false:warning
3 | dotnet_style_qualification_for_property = false:warning
4 | dotnet_style_qualification_for_method = false:warning
5 | dotnet_style_qualification_for_event = false:warning
6 | dotnet_style_require_accessibility_modifiers = never:warning
7 |
8 | csharp_style_expression_bodied_methods = true:silent
9 | csharp_style_expression_bodied_properties = true:warning
10 | csharp_style_expression_bodied_indexers = true:warning
11 | csharp_style_expression_bodied_accessors = true:warning
12 |
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Services/CodeDomFactory.cs:
--------------------------------------------------------------------------------
1 | using RevitAddin.CommandLoader.Services.CodeDom;
2 |
3 | namespace RevitAddin.CommandLoader.Services
4 | {
5 | public class CodeDomFactory
6 | {
7 | public static ICodeDomService Instance { get; private set; } = CreateCodeDomService();
8 |
9 | private static ICodeDomService CreateCodeDomService()
10 | {
11 | #if NET8_0_OR_GREATER
12 | return new CodeAnalysisCodeDomService();
13 | #else
14 | var provider = CodeProviderService.GetCSharpCodeProvider();
15 | return new CodeDomService(provider);
16 | #endif
17 | }
18 |
19 | }
20 | }
--------------------------------------------------------------------------------
/Build/Build.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | net8.0
5 |
6 | CS0649;CS0169
7 | .
8 | .
9 | 1
10 | Debug;Release
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Revit/InfoCenterUtils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace RevitAddin.CommandLoader.Revit
4 | {
5 | public static class InfoCenterUtils
6 | {
7 | public static void ShowBalloon(string title, string category = null, string uriString = null)
8 | {
9 | if (title == null) return;
10 | Autodesk.Internal.InfoCenter.ResultItem ri = new Autodesk.Internal.InfoCenter.ResultItem();
11 | ri.Category = category ?? typeof(InfoCenterUtils).Assembly.GetName().Name;
12 | ri.Title = title.Trim();
13 | if (Uri.TryCreate(uriString, UriKind.RelativeOrAbsolute, out Uri uri))
14 | ri.Uri = uri;
15 | Autodesk.Windows.ComponentManager.InfoCenterPaletteManager.ShowBalloon(ri);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/.github/workflows/Build.yml:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------------------------------
2 | # Build.yml
3 | # ------------------------------------------------------------------------------
4 |
5 | name: Build
6 |
7 | on:
8 | push:
9 | pull_request:
10 | branches-ignore:
11 | - master
12 | - main
13 | workflow_dispatch:
14 |
15 | jobs:
16 | Build:
17 | name: Build
18 | runs-on: windows-latest
19 | steps:
20 | - uses: actions/checkout@v1
21 | - name: Run './build/build.cmd'
22 | run: ./build/build.cmd --root ./build
23 | env:
24 | GitHubToken: ${{ secrets.GITHUB_TOKEN }}
25 | SignFile: ${{ secrets.SIGN_FILE }}
26 | SignPassword: ${{ secrets.SIGN_PASSWORD }}
27 | InstallationFiles: ${{ secrets.INSTALLATION_FILES }}
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Views/CompileView.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows;
3 |
4 | namespace RevitAddin.CommandLoader.Views
5 | {
6 | public partial class CompileView : Window
7 | {
8 | public CompileView()
9 | {
10 | InitializeComponent();
11 | InitializeWindow();
12 | this.KeyDown += (s, e) => { if (e.Key == System.Windows.Input.Key.Escape) { this.Close(); } };
13 | }
14 |
15 | #region InitializeWindow
16 | private void InitializeWindow()
17 | {
18 | this.SizeToContent = SizeToContent.WidthAndHeight;
19 | this.ShowInTaskbar = false;
20 | this.ResizeMode = ResizeMode.NoResize;
21 | this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
22 | }
23 | #endregion
24 | }
25 | }
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Revit/Commands/Command.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.Revit.Attributes;
2 | using Autodesk.Revit.DB;
3 | using Autodesk.Revit.UI;
4 | using System;
5 | using System.ComponentModel;
6 | using System.Threading.Tasks;
7 |
8 | namespace RevitAddin.CommandLoader.Revit.Commands
9 | {
10 | [DisplayName("Command Open - CompileView")]
11 | [Transaction(TransactionMode.Manual)]
12 | public class Command : IExternalCommand, IExternalCommandAvailability
13 | {
14 | public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elementSet)
15 | {
16 | UIApplication uiapp = commandData.Application;
17 |
18 | ViewModels.CompileViewModel.ViewModel.Show();
19 |
20 | return Result.Succeeded;
21 | }
22 |
23 | public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories)
24 | {
25 | return true;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader.Tests/CodeDom/CodeDomTester.cs:
--------------------------------------------------------------------------------
1 | using RevitAddin.CommandLoader.Services.CodeDom;
2 | using System.Reflection;
3 |
4 | namespace RevitAddin.CommandLoader.Tests.CodeDom
5 | {
6 | public class CodeDomTester
7 | {
8 | private readonly ICodeDomService codeDomService;
9 | private readonly CodeTester codeTester;
10 |
11 | public CodeDomTester(ICodeDomService codeDomService, CodeTester codeTester)
12 | {
13 | this.codeDomService = codeDomService;
14 | this.codeTester = codeTester;
15 | }
16 |
17 | public Assembly GenerateCode()
18 | {
19 | var assembly = codeDomService
20 | .SetDefines(codeTester.Defines)
21 | .GenerateCode(codeTester.Code);
22 | return assembly;
23 | }
24 |
25 | public bool Test()
26 | {
27 | var assembly = GenerateCode();
28 | return codeTester.HasMethodTest(assembly) && codeTester.HasMethodDebug(assembly);
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 ricaun
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Extensions/AppName.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reflection;
3 |
4 | namespace RevitAddin.CommandLoader.Extensions
5 | {
6 | public static class AppName
7 | {
8 | public static string GetNameVersion()
9 | {
10 | var assembly = Assembly.GetExecutingAssembly();
11 | return $"{assembly.GetName().Name} {assembly.GetName().Version.ToString(3)}";
12 | }
13 |
14 | public static string GetIcon()
15 | {
16 | return "Resources/CommandLoader.tiff";
17 | }
18 |
19 | public static string GetInfo()
20 | {
21 | var assembly = Assembly.GetExecutingAssembly();
22 | var assemblyName = assembly.GetName();
23 | var result = $"App: {assemblyName.Name}\n";
24 | result += $"Version: {assemblyName.Version.ToString(3)}\n";
25 | result += $"Location: {assembly.Location}";
26 |
27 | return result;
28 | }
29 |
30 | public static string GetUri()
31 | {
32 | return "https://github.com/ricaun-io/RevitAddin.CommandLoader";
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Revit/Commands/CommandTestGist.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.Revit.Attributes;
2 | using Autodesk.Revit.DB;
3 | using Autodesk.Revit.UI;
4 | using RevitAddin.CommandLoader.Services;
5 | using System;
6 | using System.ComponentModel;
7 |
8 | namespace RevitAddin.CommandLoader.Revit.Commands
9 | {
10 | [DisplayName("Command Test - Compile Gist")]
11 | [Transaction(TransactionMode.Manual)]
12 | public class CommandTestGist : IExternalCommand
13 | {
14 | public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elementSet)
15 | {
16 | UIApplication uiapp = commandData.Application;
17 |
18 | var gistUrl = "https://gist.github.com/ricaun/4f62b8650d29f1ff837e7e77f9e8b552";
19 |
20 | GistGithubUtils.TryGetGistString(gistUrl, out string gistContent);
21 |
22 | try
23 | {
24 | var codeDomService = CodeDomFactory.Instance;
25 | var assembly = codeDomService.GenerateCode(gistContent);
26 |
27 | App.CreateCommands(assembly);
28 | }
29 | catch (System.Exception ex)
30 | {
31 | System.Windows.MessageBox.Show(ex.ToString());
32 | }
33 |
34 | return Result.Succeeded;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader.Tests/CodeDomTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using RevitAddin.CommandLoader.Services;
3 | using RevitAddin.CommandLoader.Services.CodeDom;
4 | using RevitAddin.CommandLoader.Tests.CodeDom;
5 | using System;
6 |
7 | namespace RevitAddin.CommandLoader.Tests
8 | {
9 | public class CodeDomTests
10 | {
11 | CodeTester CodeTester = new CodeTester();
12 |
13 | public void Test_ICodeDomService(ICodeDomService codeDomService)
14 | {
15 | var assembly = codeDomService
16 | .SetDefines(CodeTester.Defines)
17 | .GenerateCode(CodeTester.Code);
18 |
19 | Console.WriteLine(assembly);
20 |
21 | Assert.IsTrue(CodeTester.HasMethodTest(assembly), "Test method not found.");
22 | Assert.IsTrue(CodeTester.HasMethodDebug(assembly), "Debug method not found.");
23 |
24 | Assert.IsTrue(CodeTester.HasMethodTest2(assembly), "Test method not found in the Tests2 class.");
25 | Assert.IsTrue(CodeTester.HasMethodDebug2(assembly), "Debug method not found in the Tests2 class.");
26 | }
27 |
28 | [Test]
29 | public void Test_CodeDomService()
30 | {
31 | var codeDomService = CodeDomFactory.Instance;
32 | Test_ICodeDomService(codeDomService);
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Views/CompileView.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
24 |
25 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Revit/Commands/CommandTestGistFiles.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.Revit.Attributes;
2 | using Autodesk.Revit.DB;
3 | using Autodesk.Revit.UI;
4 | using RevitAddin.CommandLoader.Services;
5 | using System.ComponentModel;
6 |
7 | namespace RevitAddin.CommandLoader.Revit.Commands
8 | {
9 | [DisplayName("Command Test - Compile Gist Files")]
10 | [Transaction(TransactionMode.Manual)]
11 | public class CommandTestGistFiles : IExternalCommand
12 | {
13 | public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elementSet)
14 | {
15 | UIApplication uiapp = commandData.Application;
16 |
17 | var gistUrlFiles = "https://gist.github.com/ricaun/14ec0730e7efb3cc737f2134475e2539";
18 |
19 | GistGithubUtils.TryGetGistFilesContent(gistUrlFiles, out string[] gistFilesContent);
20 |
21 | try
22 | {
23 | System.Console.WriteLine(gistFilesContent.Length);
24 | var codeDomService = CodeDomFactory.Instance;
25 | var assembly = codeDomService.GenerateCode(gistFilesContent);
26 |
27 | App.CreateCommands(assembly);
28 | }
29 | catch (System.Exception ex)
30 | {
31 | System.Windows.MessageBox.Show(ex.ToString());
32 | }
33 |
34 | return Result.Succeeded;
35 | }
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader.Tests/CodeDom/CodeTester.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | namespace RevitAddin.CommandLoader.Tests.CodeDom
4 | {
5 | public class CodeTester
6 | {
7 | const string code = """
8 | using System;
9 | public class Tests
10 | {
11 | public void Test() { }
12 | #if DEBUG
13 | public void Debug() { }
14 | #endif
15 | }
16 | """;
17 | const string code2 = """
18 | using System;
19 | public class Tests2
20 | {
21 | public void Test() { }
22 | #if DEBUG
23 | public void Debug() { }
24 | #endif
25 | }
26 | """;
27 | public string[] Code => new[] { code, code2 };
28 | public string[] Defines => new[] { "DEBUG" };
29 | public bool HasMethodTest(Assembly assembly)
30 | {
31 | var method = assembly.GetType("Tests")?.GetMethod("Test");
32 | return method is not null;
33 | }
34 | public bool HasMethodDebug(Assembly assembly)
35 | {
36 | var method = assembly.GetType("Tests")?.GetMethod("Debug");
37 | return method is not null;
38 | }
39 | public bool HasMethodTest2(Assembly assembly)
40 | {
41 | var method = assembly.GetType("Tests2")?.GetMethod("Test");
42 | return method is not null;
43 | }
44 | public bool HasMethodDebug2(Assembly assembly)
45 | {
46 | var method = assembly.GetType("Tests2")?.GetMethod("Debug");
47 | return method is not null;
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader.Tests/GistGithubUtilsTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using RevitAddin.CommandLoader.Services;
3 | using System;
4 |
5 | namespace RevitAddin.CommandLoader.Tests
6 | {
7 | public class GistGithubUtilsTests
8 | {
9 | private const string GIST_SOURCE = "https://gist.github.com/ricaun/200a576c3baa45cba034ceedac1e708e";
10 |
11 | [Test]
12 | public void Test_TryGetGistFilesContent()
13 | {
14 | var hasGistContent = GistGithubUtils.TryGetGistFilesContent(GIST_SOURCE, out string[] contents);
15 | Assert.IsTrue(hasGistContent, "Gist content not found.");
16 | }
17 |
18 | [Test]
19 | public void Test_TryGetGistModel()
20 | {
21 | var hasGistContent = GistGithubUtils.TryGetGistModel(GIST_SOURCE, out var model);
22 | Assert.IsTrue(hasGistContent, "Gist content not found.");
23 | }
24 |
25 | [Test]
26 | public void Test_TryGetGistId()
27 | {
28 | var hasGistContent = GistGithubUtils.TryGetGistId(GIST_SOURCE, out var id);
29 | Assert.IsTrue(hasGistContent, "Gist content not found.");
30 | Console.WriteLine(id);
31 | }
32 |
33 | [Test]
34 | public void Test_TryGetGistString()
35 | {
36 | var hasGistContent = GistGithubUtils.TryGetGistString(GIST_SOURCE, out string content);
37 | Assert.IsTrue(hasGistContent, "Gist content not found.");
38 | }
39 |
40 | }
41 | }
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Revit/Commands/CommandTest.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.Revit.Attributes;
2 | using Autodesk.Revit.DB;
3 | using Autodesk.Revit.UI;
4 | using RevitAddin.CommandLoader.Services;
5 | using System.ComponentModel;
6 | using System.IO;
7 | using System.Reflection;
8 |
9 | namespace RevitAddin.CommandLoader.Revit.Commands
10 | {
11 | [DisplayName("Command Test - Compile and Ribbon")]
12 | [Transaction(TransactionMode.Manual)]
13 | public class CommandTest : IExternalCommand, IExternalCommandAvailability
14 | {
15 | public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elementSet)
16 | {
17 | UIApplication uiapp = commandData.Application;
18 |
19 | try
20 | {
21 | var codeDomService = CodeDomFactory.Instance;
22 | var assembly = codeDomService.GenerateCode(
23 | CodeSamples.CommandVersion,
24 | CodeSamples.CommandTask,
25 | CodeSamples.CommandDeleteWalls);
26 |
27 | App.CreateCommands(assembly);
28 | }
29 | catch (System.Exception ex)
30 | {
31 | System.Windows.MessageBox.Show(ex.ToString());
32 | }
33 |
34 | return Result.Succeeded;
35 | }
36 |
37 | public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories)
38 | {
39 | return true;
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Extensions/AutodeskIconGeneratorUtils.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.Revit.UI;
2 | using System;
3 |
4 | namespace RevitAddin.CommandLoader.Extensions
5 | {
6 | public static class AutodeskIconGeneratorUtils
7 | {
8 | private static string[] icons = new[] { "Grey", "Red", "Orange", "Yellow", "Green", "Cyan", "Blue", "Purple", "Pink", "Brown" };
9 | private static string[] types = new[] { "Box", "Cube" };
10 | private static string[] themes = new[] { "Light", "Dark" };
11 | private static char separetor = '-';
12 | private static string extension = ".tiff";
13 | private static string url = "https://github.com/ricaun-io/Autodesk.Icon.Example/releases/download/2.0.0/";
14 |
15 | private static int icon = 0;
16 | public static bool IsDark => UIThemeManager.CurrentTheme == UITheme.Dark;
17 | public static string GetBox()
18 | {
19 | return url + CreateIcon(icon++, 0, IsDark ? 1 : 0);
20 | }
21 |
22 | public static string GetCube()
23 | {
24 | return url + CreateIcon(icon++, 1, IsDark ? 1 : 0);
25 | }
26 |
27 | private static string CreateIcon(int icon = 0, int type = 0, int theme = 0)
28 | {
29 | var typeStr = types[type % types.Length];
30 | var iconStr = icons[icon % icons.Length];
31 | var themeStr = themes[theme % themes.Length];
32 |
33 | var name = $"{typeStr}{separetor}{iconStr}";
34 | if (string.IsNullOrEmpty(themeStr) == false)
35 | name += $"{separetor}{themeStr}";
36 |
37 | return $"{name}{extension}";
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Services/CodeDom/CodeProviderService.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.CSharp;
2 | using System.CodeDom.Compiler;
3 | using System.Collections.Generic;
4 | using System.IO;
5 |
6 | namespace RevitAddin.CommandLoader.Services.CodeDom
7 | {
8 | public class CodeProviderService
9 | {
10 | public static CodeDomProvider GetCSharpCodeProvider(bool useLegacyCodeDom = false)
11 | {
12 | #if NET48_OR_GREATER
13 | if (!useLegacyCodeDom)
14 | {
15 | return NewCSharpCodeProvider();
16 | }
17 | #endif
18 | return new CSharpCodeProvider();
19 | }
20 |
21 | #if NET48_OR_GREATER
22 | ///
23 | /// NewCSharpCodeProvider
24 | /// https://github.com/aspnet/RoslynCodeDomProvider
25 | ///
26 | ///
27 | internal static CodeDomProvider NewCSharpCodeProvider()
28 | {
29 | var compilerSettings = new ProviderOptions()
30 | {
31 | CompilerFullPath = CompilerFullPath(@"roslyn/csc.exe"),
32 | CompilerServerTimeToLive = 300
33 | };
34 | return new Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider(compilerSettings);
35 | }
36 | internal class ProviderOptions : Microsoft.CodeDom.Providers.DotNetCompilerPlatform.IProviderOptions
37 | {
38 | public string CompilerFullPath { get; set; }
39 | public int CompilerServerTimeToLive { get; set; }
40 | public string CompilerVersion { get; set; }
41 | public bool WarnAsError { get; set; }
42 | public bool UseAspNetSettings { get; set; }
43 | public IDictionary AllOptions { get; set; }
44 | }
45 | private static string CompilerFullPath(string relativePath)
46 | {
47 | string frameworkFolder = Path.GetDirectoryName(typeof(CodeDomService).Assembly.Location);
48 | string compilerFullPath = Path.Combine(frameworkFolder, relativePath);
49 |
50 | return compilerFullPath;
51 | }
52 | #endif
53 | }
54 | }
--------------------------------------------------------------------------------
/Build/build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | bash --version 2>&1 | head -n 1
4 |
5 | set -eo pipefail
6 | SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
7 |
8 | ###########################################################################
9 | # CONFIGURATION
10 | ###########################################################################
11 |
12 | BUILD_PROJECT_FILE="$SCRIPT_DIR/Build.csproj"
13 | TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp"
14 |
15 | DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json"
16 | DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh"
17 | DOTNET_CHANNEL="Current"
18 |
19 | export DOTNET_CLI_TELEMETRY_OPTOUT=1
20 | export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
21 | export DOTNET_MULTILEVEL_LOOKUP=0
22 |
23 | ###########################################################################
24 | # EXECUTION
25 | ###########################################################################
26 |
27 | function FirstJsonValue {
28 | perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}"
29 | }
30 |
31 | # If dotnet CLI is installed globally and it matches requested version, use for execution
32 | if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then
33 | export DOTNET_EXE="$(command -v dotnet)"
34 | else
35 | # Download install script
36 | DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh"
37 | mkdir -p "$TEMP_DIRECTORY"
38 | curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL"
39 | chmod +x "$DOTNET_INSTALL_FILE"
40 |
41 | # If global.json exists, load expected version
42 | if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then
43 | DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")")
44 | if [[ "$DOTNET_VERSION" == "" ]]; then
45 | unset DOTNET_VERSION
46 | fi
47 | fi
48 |
49 | # Install by channel or version
50 | DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
51 | if [[ -z ${DOTNET_VERSION+x} ]]; then
52 | "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path
53 | else
54 | "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path
55 | fi
56 | export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet"
57 | fi
58 |
59 | echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)"
60 |
61 | "$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet
62 | "$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@"
63 |
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Services/CodeDom/CodeDomService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.CodeDom;
3 | using System.CodeDom.Compiler;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Reflection;
7 |
8 | namespace RevitAddin.CommandLoader.Services.CodeDom
9 | {
10 | public class CodeDomService : ICodeDomService
11 | {
12 | private CodeDomProvider provider;
13 |
14 | public CodeDomService(CodeDomProvider provider)
15 | {
16 | this.provider = provider;
17 | }
18 | private string CompilerOptions { get; set; }
19 | public ICodeDomService SetDefines(params string[] defines)
20 | {
21 | CompilerOptions = $" /define:{string.Join(";", defines).Replace(" ", "")}";
22 | return this;
23 | }
24 |
25 | public Assembly GenerateCode(params string[] sourceCode)
26 | {
27 | var compilationUnits = sourceCode
28 | .Select(s => new CodeSnippetCompileUnit(s))
29 | .ToArray();
30 |
31 | return GenerateCode(compilationUnits);
32 | }
33 |
34 | public Assembly GenerateCode(params CodeCompileUnit[] compilationUnits)
35 | {
36 | CompilerParameters compilerParametes = new CompilerParameters();
37 |
38 | compilerParametes.GenerateExecutable = false;
39 | compilerParametes.IncludeDebugInformation = false;
40 | compilerParametes.GenerateInMemory = false;
41 |
42 | compilerParametes.CompilerOptions = CompilerOptions;
43 |
44 | #region Add GetReferencedAssemblies
45 | var assemblyNames = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
46 | var nameAssemblies = new Dictionary();
47 | foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
48 | {
49 | if (assemblyNames.Any(e => e.Name == assembly.GetName().Name))
50 | {
51 | nameAssemblies[assembly.GetName().Name] = assembly;
52 | }
53 | }
54 | foreach (var keyAssembly in nameAssemblies)
55 | {
56 | compilerParametes.ReferencedAssemblies.Add(keyAssembly.Value.Location);
57 | }
58 |
59 | #endregion
60 |
61 | CompilerResults results = provider.CompileAssemblyFromDom(compilerParametes, compilationUnits);
62 | return results.CompiledAssembly;
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | All notable changes to this project will be documented in this file.
3 |
4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6 |
7 | ## [1.2.0] / 2025-03-21
8 | ### Features
9 | - Support `tiff` image files.
10 | ### Updates
11 | - Using `ricaun.Revit.UI` to `0.8.0`.
12 | - Update `AutodeskIconGeneratorUtils` to use version `2.0.0` and `tiff` file.
13 | - Add `CommandLoader.tiff` as the default image icon.
14 |
15 | ## [1.1.1] / 2024-02-27
16 | ### Features
17 | - Support [Autodesk.Icon](https://github.com/ricaun-io/Autodesk.Icon.Example) in dark theme.
18 | ### Updated
19 | - Add `AutodeskIconGeneratorUtils`.
20 | - Window close with `Esc` key.
21 |
22 | ## [1.1.0] / 2024-02-17
23 | ### Features
24 | - Support net core plugin.
25 | ### Added
26 | - Add `CodeAnalysisCodeDom` to support net code.
27 | - Update `CodeAnalysisCodeDomService` to work with multiple source code.
28 | ### Tests
29 | - Test `GistGithubUtils` download string.
30 | - Add `Newtonsoft.Json` to support `GistGithubUtils` download string.
31 |
32 | ## [1.0.6] / 2024-01-27
33 | ### Features
34 | - Using `ricaun.Revit.UI.Tasks`
35 | ### Tests
36 | - Add `CodeDom` simple test.
37 | ### Updated
38 | - Add `ICodeDomService` interface
39 | - Add `CodeDomFactory` class
40 | ### Remove
41 | - Remove `Revit.Async`
42 |
43 | ## [1.0.5] / 2023-05-05
44 | ### Features
45 | - Support C# version 7.3 in Revit 2021+ with `DotNetCompilerPlatform`.
46 | - Gist Download Files and compile.
47 | - Support `CodeDomService` with Defines - `Revit20$$` and `REVIT20$$`.
48 | ### Updated
49 | - Update `InfoCenterUtils` to show download update.
50 |
51 | ## [1.0.4] / 2023-02-03
52 | ### Updated
53 | - Update example `Command` to `Revit Version`
54 |
55 | ## [1.0.3] / 2023-02-02
56 | ### Updated
57 | - Remove Version in the `Release` folder
58 |
59 | ## [1.0.2] / 2023-02-02
60 | ### Fixed
61 | - Fix `GithubRequestService` repository
62 |
63 | ## [1.0.1] / 2023-02-02
64 | ### Added
65 | - Add Debug color Panel Title Background
66 | ### Fixed
67 | - Fix Image load problem
68 |
69 | ## [1.0.0] / 2023-02-02
70 | ### Features
71 | - [x] Compile multiple `IExternalCommand` UI
72 | - [x] Code Compiler
73 | - [x] Add Command to Ribbon
74 | - [x] AutoUpdater
75 |
76 | [vNext]: ../../compare/1.0.0...HEAD
77 | [1.2.0]: ../../compare/1.1.1...1.2.0
78 | [1.1.1]: ../../compare/1.1.0...1.1.1
79 | [1.1.0]: ../../compare/1.0.6...1.1.0
80 | [1.0.6]: ../../compare/1.0.5...1.0.6
81 | [1.0.5]: ../../compare/1.0.4...1.0.5
82 | [1.0.4]: ../../compare/1.0.3...1.0.4
83 | [1.0.3]: ../../compare/1.0.2...1.0.3
84 | [1.0.2]: ../../compare/1.0.1...1.0.2
85 | [1.0.1]: ../../compare/1.0.0...1.0.1
86 | [1.0.0]: ../../compare/1.0.0
--------------------------------------------------------------------------------
/Build/build.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | Param(
3 | [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
4 | [string[]]$BuildArguments
5 | )
6 |
7 | Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)"
8 |
9 | Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 }
10 | $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
11 |
12 | ###########################################################################
13 | # CONFIGURATION
14 | ###########################################################################
15 |
16 | $BuildProjectFile = "$PSScriptRoot\Build.csproj"
17 | $TempDirectory = "$PSScriptRoot\\.nuke\temp"
18 |
19 | $DotNetGlobalFile = "$PSScriptRoot\\global.json"
20 | $DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1"
21 | $DotNetChannel = "Current"
22 |
23 | $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1
24 | $env:DOTNET_CLI_TELEMETRY_OPTOUT = 1
25 | $env:DOTNET_MULTILEVEL_LOOKUP = 0
26 |
27 | ###########################################################################
28 | # EXECUTION
29 | ###########################################################################
30 |
31 | function ExecSafe([scriptblock] $cmd) {
32 | & $cmd
33 | if ($LASTEXITCODE) { exit $LASTEXITCODE }
34 | }
35 |
36 | # If dotnet CLI is installed globally and it matches requested version, use for execution
37 | if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and `
38 | $(dotnet --version) -and $LASTEXITCODE -eq 0) {
39 | $env:DOTNET_EXE = (Get-Command "dotnet").Path
40 | }
41 | else {
42 | # Download install script
43 | $DotNetInstallFile = "$TempDirectory\dotnet-install.ps1"
44 | New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null
45 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
46 | (New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile)
47 |
48 | # If global.json exists, load expected version
49 | if (Test-Path $DotNetGlobalFile) {
50 | $DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
51 | if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
52 | $DotNetVersion = $DotNetGlobal.sdk.version
53 | }
54 | }
55 |
56 | # Install by channel or version
57 | $DotNetDirectory = "$TempDirectory\dotnet-win"
58 | if (!(Test-Path variable:DotNetVersion)) {
59 | ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath }
60 | } else {
61 | ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath }
62 | }
63 | $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe"
64 | }
65 |
66 | Write-Output "Microsoft (R) .NET Core SDK version $(& $env:DOTNET_EXE --version)"
67 |
68 | ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet }
69 | ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments }
70 |
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Services/CodeDom/CodeAnalysisCodeDomService.cs:
--------------------------------------------------------------------------------
1 | #if NET8_0_OR_GREATER
2 |
3 | using Microsoft.CodeAnalysis;
4 | using Microsoft.CodeAnalysis.CSharp;
5 | using Microsoft.CodeAnalysis.Text;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.IO;
9 | using System.Linq;
10 | using System.Reflection;
11 |
12 | namespace RevitAddin.CommandLoader.Services.CodeDom
13 | {
14 | public class CodeAnalysisCodeDomService : ICodeDomService
15 | {
16 | private string[] PreprocessorSymbols { get; set; }
17 | public ICodeDomService SetDefines(params string[] defines)
18 | {
19 | PreprocessorSymbols = defines;
20 | return this;
21 | }
22 |
23 | public Assembly GenerateCode(params string[] sourceCode)
24 | {
25 | var compilation = CompilationCode(sourceCode, PreprocessorSymbols);
26 |
27 | var filePath = Path.Combine(Path.GetTempPath(), compilation.Assembly.Name + ".dll");
28 | using (var file = File.Create(filePath))
29 | {
30 | var result = compilation.Emit(file);
31 | }
32 |
33 | return Assembly.LoadFrom(filePath);
34 | }
35 |
36 | private CSharpCompilation CompilationCode(string[] sourceCodes, string[] preprocessorSymbols = null)
37 | {
38 | var options = CSharpParseOptions.Default
39 | .WithLanguageVersion(LanguageVersion.Latest)
40 | .WithPreprocessorSymbols(preprocessorSymbols);
41 |
42 | var parsedSyntaxTrees = sourceCodes
43 | .Select(sourceCode => SyntaxFactory.ParseSyntaxTree(sourceCode, options))
44 | .ToArray();
45 |
46 | var references = new List
47 | {
48 | MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
49 | MetadataReference.CreateFromFile(typeof(Console).Assembly.Location)
50 | };
51 |
52 | #region Add GetReferencedAssemblies
53 | var assemblyNames = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
54 | var nameAssemblies = new Dictionary();
55 | foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
56 | {
57 | if (assemblyNames.Any(e => e.Name == assembly.GetName().Name))
58 | {
59 | nameAssemblies[assembly.GetName().Name] = assembly;
60 | }
61 | }
62 | foreach (var keyAssembly in nameAssemblies)
63 | {
64 | references.Add(MetadataReference.CreateFromFile(keyAssembly.Value.Location));
65 | }
66 | #endregion
67 |
68 | return CSharpCompilation.Create(Guid.NewGuid().ToString(),
69 | parsedSyntaxTrees,
70 | references: references,
71 | options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary,
72 | optimizationLevel: OptimizationLevel.Release,
73 | assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default));
74 | }
75 | }
76 | }
77 |
78 | #endif
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader.Tests/RevitAddin.CommandLoader.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 | Latest
6 | Debug 2017;2017;Debug 2021;2021;2025;Debug 2025
7 |
8 |
9 |
10 |
11 |
12 |
13 | 2017
14 | net46
15 |
16 |
17 |
18 |
19 | 2018
20 | net46
21 |
22 |
23 |
24 |
25 | 2019
26 | net47
27 |
28 |
29 |
30 |
31 | 2020
32 | net47
33 |
34 |
35 |
36 |
37 | 2021
38 | net48
39 |
40 |
41 |
42 |
43 | 2022
44 | net48
45 |
46 |
47 |
48 |
49 | 2024
50 | net48
51 |
52 |
53 |
54 |
55 | 2025
56 | net8.0-windows
57 |
58 |
59 |
60 |
61 | 2017
62 | net46
63 |
64 |
65 |
66 |
67 |
68 |
69 | REVIT$(RevitVersion)
70 |
71 |
72 |
73 |
74 | true
75 | true
76 | false
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | NU1903
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Extensions/AttributeExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 |
6 | namespace System.Reflection
7 | {
8 | ///
9 | /// A static class containing methods for working with custom attributes.
10 | ///
11 | public static class AttributeExtension
12 | {
13 | ///
14 | /// Checks if a custom attribute provider has any attributes of the specified type.
15 | ///
16 | /// The type of attribute to check for.
17 | /// The custom attribute provider.
18 | /// True if the custom attribute provider has any attributes of the specified type, false otherwise.
19 | public static bool AnyAttribute(
20 | this ICustomAttributeProvider customAttributeProvider)
21 | where TCustomAttributeType : Attribute
22 | {
23 | return GetAttribute(customAttributeProvider) is not null;
24 | }
25 | ///
26 | /// Gets attributes of the specified type from a custom attribute provider.
27 | ///
28 | /// The type of attribute to get.
29 | /// The custom attribute provider.
30 | /// The attributes of the specified type from the custom attribute provider.
31 | public static IEnumerable GetAttributes(
32 | this ICustomAttributeProvider customAttributeProvider)
33 | where TCustomAttributeType : Attribute
34 | {
35 | return customAttributeProvider
36 | .GetCustomAttributes(typeof(TCustomAttributeType), true)
37 | .OfType();
38 | }
39 | ///
40 | /// Gets the first attribute of the specified type from a custom attribute provider.
41 | ///
42 | /// The type of attribute to get.
43 | /// The custom attribute provider.
44 | /// The first attribute of the specified type from the custom attribute provider.
45 | public static TCustomAttributeType GetAttribute(
46 | this ICustomAttributeProvider customAttributeProvider)
47 | where TCustomAttributeType : Attribute
48 | {
49 | return customAttributeProvider
50 | .GetAttributes()
51 | .FirstOrDefault();
52 | }
53 | ///
54 | /// Tries to get the first attribute of the specified type from a custom attribute provider.
55 | ///
56 | /// The type of attribute to get.
57 | /// The custom attribute provider.
58 | /// The first attribute of the specified type from the custom attribute provider.
59 | /// True if the attribute was found, false otherwise.
60 | public static bool TryGetAttribute(
61 | this ICustomAttributeProvider customAttributeProvider,
62 | out TCustomAttributeType customAttributeType)
63 | where TCustomAttributeType : Attribute
64 | {
65 | customAttributeType = GetAttribute(customAttributeProvider);
66 | return customAttributeType is not null;
67 | }
68 | }
69 | }
--------------------------------------------------------------------------------
/RevitAddin.CommandLoader/Services/JsonService.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 |
3 | namespace RevitAddin.CommandLoader.Services
4 | {
5 | ///
6 | /// JsonService
7 | ///
8 | public class JsonService : JsonService