From 5259548c23cb235e1f06364a31232c414a47c7b9 Mon Sep 17 00:00:00 2001 From: GeKtvi <61162497+GeKtvi@users.noreply.github.com> Date: Thu, 1 May 2025 21:55:53 +0300 Subject: [PATCH 1/3] Added type safe property access --- .../Errors/SolidDnaErrorCode.cs | 4 + .../CustomProperties/CustomPropertyEditor.cs | 136 +++++++++++++++++- 2 files changed, 138 insertions(+), 2 deletions(-) diff --git a/SolidDna/CADBooster.SolidDna/Errors/SolidDnaErrorCode.cs b/SolidDna/CADBooster.SolidDna/Errors/SolidDnaErrorCode.cs index f7e6cf1e..e6a730f1 100644 --- a/SolidDna/CADBooster.SolidDna/Errors/SolidDnaErrorCode.cs +++ b/SolidDna/CADBooster.SolidDna/Errors/SolidDnaErrorCode.cs @@ -169,6 +169,10 @@ public enum SolidDnaErrorCode /// SolidWorksModelGetConfigurationError = 11014, + /// + /// + SolidWorksModelGetPropertyError = 11030, + #endregion #region SolidWorks Command Manager (12,000) diff --git a/SolidDna/CADBooster.SolidDna/SolidWorks/CustomProperties/CustomPropertyEditor.cs b/SolidDna/CADBooster.SolidDna/SolidWorks/CustomProperties/CustomPropertyEditor.cs index 71ba0c2b..dc8f59eb 100644 --- a/SolidDna/CADBooster.SolidDna/SolidWorks/CustomProperties/CustomPropertyEditor.cs +++ b/SolidDna/CADBooster.SolidDna/SolidWorks/CustomProperties/CustomPropertyEditor.cs @@ -1,6 +1,8 @@ using SolidWorks.Interop.sldworks; using SolidWorks.Interop.swconst; +using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; namespace CADBooster.SolidDna @@ -10,6 +12,7 @@ namespace CADBooster.SolidDna /// public class CustomPropertyEditor : SolidDnaObject { + public bool IsTypeCheckEnabled { get; set; } = true; #region Constructor /// @@ -45,12 +48,107 @@ public string GetCustomProperty(string name, bool resolve = false) // TODO: Add error checking and exception catching // Get custom property - BaseObject.Get5(name, false, out var val, out var resolvedVal, out var wasResolved); + _ = BaseObject.Get5(name, false, out var val, out var resolvedVal, out _); // Return desired result return resolve ? resolvedVal : val; } + public string GetStringCustomProperty(string name, bool resolve = false) + { + // TODO: Add error checking and exception catching + + if (IsTypeCheckEnabled) + ThrowIfExpectedTypeMismatch(name, swCustomInfoType_e.swCustomInfoText, true); + + _ = BaseObject.Get5(name, false, out var val, out var resolvedVal, out _); + + return resolve ? resolvedVal : val; + } + + public DateTime GetDateCustomProperty(string name) + { + // TODO: Add error checking and exception catching + + if (IsTypeCheckEnabled) + ThrowIfExpectedTypeMismatch(name, swCustomInfoType_e.swCustomInfoDate); + + + _ = BaseObject.Get5(name, false, out _, out var resolvedVal, out _); + + return DateTime.Parse(resolvedVal); + } + + public int GetIntegerCustomProperty(string name) + { + // TODO: Add error checking and exception catching + + if (IsTypeCheckEnabled) + ThrowIfExpectedTypeMismatch(name, swCustomInfoType_e.swCustomInfoNumber); + + + _ = BaseObject.Get5(name, false, out _, out var resolvedVal, out _); + + return int.Parse(resolvedVal); + } + + public double GetDoubleCustomProperty(string name) + { + // TODO: Add error checking and exception catching + + if (IsTypeCheckEnabled) + ThrowIfExpectedTypeMismatch(name, swCustomInfoType_e.swCustomInfoNumber); + + + _ = BaseObject.Get5(name, false, out _, out var resolvedVal, out _); + + return double.Parse(resolvedVal, CultureInfo.InvariantCulture); + } + + public bool GetBooleanCustomProperty(string name) + { + // TODO: Add error checking and exception catching + + if (IsTypeCheckEnabled) + ThrowIfExpectedTypeMismatch(name, swCustomInfoType_e.swCustomInfoYesOrNo); + + _ = BaseObject.Get5(name, false, out _, out var resolvedVal, out _); + + switch (resolvedVal) + { + case "Yes": + return true; + case "No": + return false; + default: + throw new InvalidOperationException(); + } + } + + public string GetRawEquationCustomProperty(string name) + { + // TODO: Add error checking and exception catching + + if (IsTypeCheckEnabled) + ThrowIfExpectedTypeMismatch(name, swCustomInfoType_e.swCustomInfoEquation, true); + + _ = BaseObject.Get5(name, false, out var val, out _, out _); + + return val; + } + + public double GetEvaluatedEquationCustomProperty(string name) + { + // TODO: Add error checking and exception catching + + if (IsTypeCheckEnabled) + ThrowIfExpectedTypeMismatch(name, swCustomInfoType_e.swCustomInfoEquation); + + _ = BaseObject.Get5(name, false, out _, out var resolvedVal, out _); + + return double.Parse(resolvedVal, CultureInfo.InvariantCulture); + } + /// /// Sets the value of a custom property by name /// @@ -72,9 +170,28 @@ public void SetCustomProperty(string name, string value, swCustomInfoType_e type // // Set new one - BaseObject.Add3(name, (int)type, value, (int)swCustomPropertyAddOption_e.swCustomPropertyReplaceValue); + _ = BaseObject.Add3(name, (int)type, value, (int)swCustomPropertyAddOption_e.swCustomPropertyReplaceValue); } + public void SetStringCustomProperty(string name, string value) + => SetCustomProperty(name, value, swCustomInfoType_e.swCustomInfoText); + + public void SetDateCustomProperty(string name, DateTime value) + => SetCustomProperty(name, value.ToString("dd.MM.yyyy"), swCustomInfoType_e.swCustomInfoDate); + + public void SetIntegerCustomProperty(string name, int value) + => SetCustomProperty(name, value.ToString(), swCustomInfoType_e.swCustomInfoNumber); + + public void SetDoubleCustomProperty(string name, double value) + => SetCustomProperty(name, value.ToString(CultureInfo.InvariantCulture), swCustomInfoType_e.swCustomInfoDouble); + + public void SetBooleanCustomProperty(string name, bool value) + => SetCustomProperty(name, value ? "Yes" : "No", swCustomInfoType_e.swCustomInfoYesOrNo); + + public void SetEquationCustomProperty(string name, string value) + => SetCustomProperty(name, value, swCustomInfoType_e.swCustomInfoEquation); + + /// /// Deletes a custom property by name /// @@ -107,5 +224,20 @@ public List GetCustomProperties() // Return the list return list; } + + private void ThrowIfExpectedTypeMismatch(string name, swCustomInfoType_e expectedType, bool allowUnknown = false) + { + var type = (swCustomInfoType_e)BaseObject.GetType2(name); + + if (allowUnknown && type == swCustomInfoType_e.swCustomInfoUnknown) + return; + + if (type != expectedType) + { + throw new SolidDnaException(SolidDnaErrors.CreateError( + SolidDnaErrorTypeCode.SolidWorksModel, SolidDnaErrorCode.SolidWorksModelError, + $"Property has different type that expected. Received: {type}, expected: {expectedType}")); + } + } } } From 6d75111a0ef69202115319fb29d8b6c64211fc0e Mon Sep 17 00:00:00 2001 From: GeKtvi <61162497+GeKtvi@users.noreply.github.com> Date: Thu, 1 May 2025 22:20:52 +0300 Subject: [PATCH 2/3] Added comments about property access --- .../Errors/SolidDnaErrorCode.cs | 1 + .../CustomProperties/CustomPropertyEditor.cs | 98 +++++++++++++++++-- 2 files changed, 92 insertions(+), 7 deletions(-) diff --git a/SolidDna/CADBooster.SolidDna/Errors/SolidDnaErrorCode.cs b/SolidDna/CADBooster.SolidDna/Errors/SolidDnaErrorCode.cs index e6a730f1..b9ea7657 100644 --- a/SolidDna/CADBooster.SolidDna/Errors/SolidDnaErrorCode.cs +++ b/SolidDna/CADBooster.SolidDna/Errors/SolidDnaErrorCode.cs @@ -170,6 +170,7 @@ public enum SolidDnaErrorCode SolidWorksModelGetConfigurationError = 11014, /// + /// Error occurred while trying to get a custom property value from a SolidWorks model /// SolidWorksModelGetPropertyError = 11030, diff --git a/SolidDna/CADBooster.SolidDna/SolidWorks/CustomProperties/CustomPropertyEditor.cs b/SolidDna/CADBooster.SolidDna/SolidWorks/CustomProperties/CustomPropertyEditor.cs index dc8f59eb..a08d6863 100644 --- a/SolidDna/CADBooster.SolidDna/SolidWorks/CustomProperties/CustomPropertyEditor.cs +++ b/SolidDna/CADBooster.SolidDna/SolidWorks/CustomProperties/CustomPropertyEditor.cs @@ -12,6 +12,11 @@ namespace CADBooster.SolidDna /// public class CustomPropertyEditor : SolidDnaObject { + /// + /// Gets or sets whether type checking is enabled when getting property values + /// When enabled, methods will verify the property type matches the expected type + /// By default is + /// public bool IsTypeCheckEnabled { get; set; } = true; #region Constructor @@ -29,7 +34,7 @@ public CustomPropertyEditor(CustomPropertyManager model) : base(model) /// Checks if a custom property exists /// /// The name of the custom property - /// + /// If the property exists , otherwise public bool CustomPropertyExists(string name) { // TODO: Add error checking and exception catching @@ -42,7 +47,7 @@ public bool CustomPropertyExists(string name) /// /// The name of the custom property /// True to resolve the custom property value - /// + /// The property value as a string public string GetCustomProperty(string name, bool resolve = false) { // TODO: Add error checking and exception catching @@ -54,6 +59,13 @@ public string GetCustomProperty(string name, bool resolve = false) return resolve ? resolvedVal : val; } + /// + /// Gets a string value from a custom property + /// + /// The name of the custom property + /// Whether to resolve the value (evaluate equations/formulas) + /// The string value of the property + /// Thrown if type checking is enabled and the property is not of text type public string GetStringCustomProperty(string name, bool resolve = false) { // TODO: Add error checking and exception catching @@ -66,6 +78,12 @@ public string GetStringCustomProperty(string name, bool resolve = false) return resolve ? resolvedVal : val; } + /// + /// Gets a DateTime value from a date-type custom property + /// + /// The name of the custom property + /// The parsed DateTime value + /// Thrown if type checking is enabled and the property is not of date type public DateTime GetDateCustomProperty(string name) { // TODO: Add error checking and exception catching @@ -77,8 +95,14 @@ public DateTime GetDateCustomProperty(string name) _ = BaseObject.Get5(name, false, out _, out var resolvedVal, out _); return DateTime.Parse(resolvedVal); - } - + } + + /// + /// Gets an integer value from a number-type custom property + /// + /// The name of the custom property + /// The parsed integer value + /// Thrown if type checking is enabled and the property is not of number type public int GetIntegerCustomProperty(string name) { // TODO: Add error checking and exception catching @@ -90,8 +114,14 @@ public int GetIntegerCustomProperty(string name) _ = BaseObject.Get5(name, false, out _, out var resolvedVal, out _); return int.Parse(resolvedVal); - } - + } + + /// + /// Gets a double value from a number-type custom property + /// + /// The name of the custom property + /// The parsed double value + /// Thrown if type checking is enabled and the property is not of number type public double GetDoubleCustomProperty(string name) { // TODO: Add error checking and exception catching @@ -105,6 +135,12 @@ public double GetDoubleCustomProperty(string name) return double.Parse(resolvedVal, CultureInfo.InvariantCulture); } + /// + /// Gets a boolean value from a yes/no-type custom property + /// + /// The name of the custom property + /// The boolean value ( for "Yes", for "No") + /// Thrown if type checking is enabled and the property is not of yes/no type public bool GetBooleanCustomProperty(string name) { // TODO: Add error checking and exception catching @@ -125,6 +161,12 @@ public bool GetBooleanCustomProperty(string name) } } + /// + /// Gets the raw equation text from an equation-type custom property + /// + /// The name of the custom property + /// The raw equation text + /// Thrown if type checking is enabled and the property is not of equation type public string GetRawEquationCustomProperty(string name) { // TODO: Add error checking and exception catching @@ -137,6 +179,12 @@ public string GetRawEquationCustomProperty(string name) return val; } + /// + /// Gets the evaluated result of an equation-type custom property + /// + /// The name of the custom property + /// The evaluated numeric result + /// Thrown if type checking is enabled and the property is not of equation type public double GetEvaluatedEquationCustomProperty(string name) { // TODO: Add error checking and exception catching @@ -173,25 +221,54 @@ public void SetCustomProperty(string name, string value, swCustomInfoType_e type _ = BaseObject.Add3(name, (int)type, value, (int)swCustomPropertyAddOption_e.swCustomPropertyReplaceValue); } + /// + /// Sets a string value to a text-type custom property + /// + /// The name of the custom property + /// The string value to set public void SetStringCustomProperty(string name, string value) => SetCustomProperty(name, value, swCustomInfoType_e.swCustomInfoText); + /// + /// Sets a date value to a date-type custom property, time data is ignored + /// + /// The name of the custom property + /// The date value to set public void SetDateCustomProperty(string name, DateTime value) => SetCustomProperty(name, value.ToString("dd.MM.yyyy"), swCustomInfoType_e.swCustomInfoDate); + /// + /// Sets an integer value to a number-type custom property + /// + /// The name of the custom property + /// The integer value to set public void SetIntegerCustomProperty(string name, int value) => SetCustomProperty(name, value.ToString(), swCustomInfoType_e.swCustomInfoNumber); + /// + /// Sets a double value to a number-type custom property + /// + /// The name of the custom property + /// The double value to set public void SetDoubleCustomProperty(string name, double value) => SetCustomProperty(name, value.ToString(CultureInfo.InvariantCulture), swCustomInfoType_e.swCustomInfoDouble); + /// + /// Sets a boolean value to a yes/no-type custom property ("Yes" for , "No" for ) + /// + /// The name of the custom property + /// The boolean value to set public void SetBooleanCustomProperty(string name, bool value) => SetCustomProperty(name, value ? "Yes" : "No", swCustomInfoType_e.swCustomInfoYesOrNo); + /// + /// Sets an equation/formula to an equation-type custom property + /// + /// The name of the custom property + /// The equation text to set public void SetEquationCustomProperty(string name, string value) => SetCustomProperty(name, value, swCustomInfoType_e.swCustomInfoEquation); - /// /// Deletes a custom property by name /// @@ -225,6 +302,13 @@ public List GetCustomProperties() return list; } + /// + /// Throws an exception if the actual property type doesn't match the expected type + /// + /// The name of the property to check + /// The expected property type + /// Whether to allow unknown/untyped properties + /// Thrown if the property type doesn't match the expected type private void ThrowIfExpectedTypeMismatch(string name, swCustomInfoType_e expectedType, bool allowUnknown = false) { var type = (swCustomInfoType_e)BaseObject.GetType2(name); From e53ecad4e969929c4ceb4bdafac1b4b1fe1867b1 Mon Sep 17 00:00:00 2001 From: GeKtvi <61162497+GeKtvi@users.noreply.github.com> Date: Sat, 3 May 2025 19:35:15 +0300 Subject: [PATCH 3/3] Fixed date serialization in property setter --- .../SolidWorks/CustomProperties/CustomPropertyEditor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SolidDna/CADBooster.SolidDna/SolidWorks/CustomProperties/CustomPropertyEditor.cs b/SolidDna/CADBooster.SolidDna/SolidWorks/CustomProperties/CustomPropertyEditor.cs index a08d6863..e3245dc5 100644 --- a/SolidDna/CADBooster.SolidDna/SolidWorks/CustomProperties/CustomPropertyEditor.cs +++ b/SolidDna/CADBooster.SolidDna/SolidWorks/CustomProperties/CustomPropertyEditor.cs @@ -235,7 +235,7 @@ public void SetStringCustomProperty(string name, string value) /// The name of the custom property /// The date value to set public void SetDateCustomProperty(string name, DateTime value) - => SetCustomProperty(name, value.ToString("dd.MM.yyyy"), swCustomInfoType_e.swCustomInfoDate); + => SetCustomProperty(name, value.Date.ToShortDateString(), swCustomInfoType_e.swCustomInfoDate); /// /// Sets an integer value to a number-type custom property