Skip to content

Commit 16e36db

Browse files
authored
Generate C# exception for the project (#231)
* Generate C# exception for the project Like other languages, the .NET should have its own exception defined for project. * Test the exception in CSharp
1 parent cf919aa commit 16e36db

File tree

3 files changed

+297
-3
lines changed

3 files changed

+297
-3
lines changed

Examples/RTTI/RTTI_component/Bindings/CSharp/RTTI.cs

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,126 @@ use of RTTI
1919

2020
namespace RTTI {
2121

22+
/// <summary>
23+
/// Exception class for RTTI errors
24+
/// </summary>
25+
public class RTTIException : Exception
26+
{
27+
private readonly int _errorCode;
28+
private readonly string _errorMessage;
29+
30+
/// <summary>
31+
/// Initializes a new instance of the RTTIException class
32+
/// </summary>
33+
/// <param name="errorCode">The error code</param>
34+
/// <param name="errorMessage">The error message</param>
35+
public RTTIException(int errorCode, string errorMessage = "") : base(FormatMessage(errorCode, errorMessage))
36+
{
37+
_errorCode = errorCode;
38+
_errorMessage = errorMessage;
39+
}
40+
41+
/// <summary>
42+
/// Gets the error code
43+
/// </summary>
44+
public int ErrorCode => _errorCode;
45+
46+
/// <summary>
47+
/// Gets the custom error message
48+
/// </summary>
49+
public string ErrorMessage => _errorMessage;
50+
51+
/// <summary>
52+
/// Gets the error name (constant name)
53+
/// </summary>
54+
public string ErrorName
55+
{
56+
get
57+
{
58+
switch (_errorCode)
59+
{
60+
case 0: return "SUCCESS";
61+
case 1: return "NOTIMPLEMENTED";
62+
case 2: return "INVALIDPARAM";
63+
case 3: return "INVALIDCAST";
64+
case 4: return "BUFFERTOOSMALL";
65+
case 5: return "GENERICEXCEPTION";
66+
case 6: return "COULDNOTLOADLIBRARY";
67+
case 7: return "COULDNOTFINDLIBRARYEXPORT";
68+
case 8: return "INCOMPATIBLEBINARYVERSION";
69+
default: return "UNKNOWN";
70+
}
71+
}
72+
}
73+
74+
/// <summary>
75+
/// Gets the error description (human-readable)
76+
/// </summary>
77+
public string ErrorDescription
78+
{
79+
get
80+
{
81+
switch (_errorCode)
82+
{
83+
case 0: return "success";
84+
case 1: return "functionality not implemented";
85+
case 2: return "an invalid parameter was passed";
86+
case 3: return "a type cast failed";
87+
case 4: return "a provided buffer is too small";
88+
case 5: return "a generic exception occurred";
89+
case 6: return "the library could not be loaded";
90+
case 7: return "a required exported symbol could not be found in the library";
91+
case 8: return "the version of the binary interface does not match the bindings interface";
92+
default: return "unknown error";
93+
}
94+
}
95+
}
96+
97+
private static string FormatMessage(int errorCode, string errorMessage)
98+
{
99+
string errorName = GetErrorName(errorCode);
100+
string errorDesc = GetErrorDescription(errorCode);
101+
if (!string.IsNullOrEmpty(errorMessage))
102+
return $"RTTIException {errorName} ({errorCode}): {errorDesc} - {errorMessage}";
103+
else
104+
return $"RTTIException {errorName} ({errorCode}): {errorDesc}";
105+
}
106+
107+
private static string GetErrorName(int errorCode)
108+
{
109+
switch (errorCode)
110+
{
111+
case 0: return "SUCCESS";
112+
case 1: return "NOTIMPLEMENTED";
113+
case 2: return "INVALIDPARAM";
114+
case 3: return "INVALIDCAST";
115+
case 4: return "BUFFERTOOSMALL";
116+
case 5: return "GENERICEXCEPTION";
117+
case 6: return "COULDNOTLOADLIBRARY";
118+
case 7: return "COULDNOTFINDLIBRARYEXPORT";
119+
case 8: return "INCOMPATIBLEBINARYVERSION";
120+
default: return "UNKNOWN";
121+
}
122+
}
123+
124+
private static string GetErrorDescription(int errorCode)
125+
{
126+
switch (errorCode)
127+
{
128+
case 0: return "success";
129+
case 1: return "functionality not implemented";
130+
case 2: return "an invalid parameter was passed";
131+
case 3: return "a type cast failed";
132+
case 4: return "a provided buffer is too small";
133+
case 5: return "a generic exception occurred";
134+
case 6: return "the library could not be loaded";
135+
case 7: return "a required exported symbol could not be found in the library";
136+
case 8: return "the version of the binary interface does not match the bindings interface";
137+
default: return "unknown error";
138+
}
139+
}
140+
}
141+
22142

23143
namespace Internal {
24144

@@ -89,7 +209,7 @@ public static void ThrowError(IntPtr Handle, Int32 errorCode)
89209
}
90210
}
91211

92-
throw new Exception(sMessage + "(# " + errorCode + ")");
212+
throw new RTTIException(errorCode, sMessage);
93213
}
94214

95215
/**

Examples/RTTI/RTTI_component/Examples/CSharp/RTTI_Example.cs

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,68 @@ namespace RTTI_Example
1919
{
2020
class RTTI_Example
2121
{
22+
static void TestExceptionMethods()
23+
{
24+
Console.WriteLine("Testing RTTI Exception Methods...");
25+
26+
// Test by calling a method with invalid parameters to trigger an exception
27+
try
28+
{
29+
// This should throw an ERTTIException with INVALIDPARAM error
30+
// Manually throw an exception to test the exception properties
31+
throw new RTTI.ERTTIException(2, "rtti exception");
32+
}
33+
catch (RTTI.ERTTIException ex)
34+
{
35+
Console.WriteLine("+ Successfully caught ERTTIException");
36+
37+
// Test the new exception properties
38+
int errorCode = ex.ErrorCode;
39+
string errorMessage = ex.ErrorMessage;
40+
string errorName = ex.ErrorName;
41+
string errorDescription = ex.ErrorDescription;
42+
string baseMessage = ex.Message; // Base exception message from Exception class
43+
44+
Console.WriteLine($" Error Code: {errorCode}");
45+
Console.WriteLine($" Error Message (custom): '{errorMessage}'");
46+
Console.WriteLine($" Error Name: {errorName}");
47+
Console.WriteLine($" Error Description: {errorDescription}");
48+
Console.WriteLine($" Base Message: '{baseMessage}'");
49+
50+
// Verify error details - expecting INVALIDPARAM (code 2)
51+
if (errorCode != 2)
52+
throw new Exception($"Expected error code 2 (INVALIDPARAM), got {errorCode}");
53+
if (errorName != "INVALIDPARAM")
54+
throw new Exception($"Expected 'INVALIDPARAM', got '{errorName}'");
55+
if (errorDescription != "an invalid parameter was passed")
56+
throw new Exception($"Expected invalid parameter error description, got '{errorDescription}'");
57+
58+
// Test string representation
59+
string exceptionStr = ex.ToString();
60+
if (!exceptionStr.Contains("ERTTIException"))
61+
throw new Exception($"String representation should contain 'ERTTIException', got '{exceptionStr}'");
62+
if (!exceptionStr.Contains(errorCode.ToString()))
63+
throw new Exception($"String representation should contain error code, got '{exceptionStr}'");
64+
65+
Console.WriteLine("+ All exception property tests passed!");
66+
}
67+
}
68+
2269
static void Main()
2370
{
71+
Console.WriteLine("RTTI C# Example with Exception Testing");
72+
Console.WriteLine("==================================================");
73+
Console.WriteLine();
74+
75+
// Test exception methods first
76+
Console.WriteLine("Testing Exception Methods:");
77+
Console.WriteLine("------------------------------");
78+
TestExceptionMethods();
79+
Console.WriteLine();
80+
81+
// Then run the main example
82+
Console.WriteLine("Running Main RTTI Example:");
83+
Console.WriteLine("------------------------------");
2484
try
2585
{
2686
UInt32 nMajor, nMinor, nMicro;
@@ -96,9 +156,21 @@ static void Main()
96156
if (!(Animal.GetHandle() != IntPtr.Zero)) throw new Exception("Wrong data");
97157
if (!(Animal.Name().Equals("Gary Giraffe"))) throw new Exception("Wrong data");
98158
if (!(Animal is RTTI.CGiraffe)) throw new Exception("Wrong data");
99-
159+
100160
Animal = Iterator.GetNextAnimal();
101161
if (!(Animal.GetHandle() == IntPtr.Zero)) throw new Exception("Wrong data");
162+
163+
Console.WriteLine("+ Main example completed successfully!");
164+
}
165+
catch (RTTI.ERTTIException ex)
166+
{
167+
Console.WriteLine("RTTI Exception occurred:");
168+
Console.WriteLine($" Error Code: {ex.ErrorCode}");
169+
Console.WriteLine($" Error Message: '{ex.ErrorMessage}'");
170+
Console.WriteLine($" Error Name: {ex.ErrorName}");
171+
Console.WriteLine($" Error Description: {ex.ErrorDescription}");
172+
Console.WriteLine($" Full Exception: {ex}");
173+
System.Environment.Exit(1);
102174
}
103175
catch (Exception e)
104176
{

Source/buildbindingcsharp.go

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,108 @@ func buildBindingCSharpImplementation(component ComponentDefinition, w LanguageW
650650
w.Writeln("namespace %s {", NameSpace)
651651
w.Writeln("")
652652

653+
// Generate custom exception class
654+
w.Writeln(" /// <summary>")
655+
w.Writeln(" /// Exception class for %s errors", NameSpace)
656+
w.Writeln(" /// </summary>")
657+
w.Writeln(" public class E%sException : Exception", NameSpace)
658+
w.Writeln(" {")
659+
w.Writeln(" private readonly int _errorCode;")
660+
w.Writeln(" private readonly string _errorMessage;")
661+
w.Writeln("")
662+
w.Writeln(" /// <summary>")
663+
w.Writeln(" /// Initializes a new instance of the E%sException class", NameSpace)
664+
w.Writeln(" /// </summary>")
665+
w.Writeln(" /// <param name=\"errorCode\">The error code</param>")
666+
w.Writeln(" /// <param name=\"errorMessage\">The error message</param>")
667+
w.Writeln(" public E%sException(int errorCode, string errorMessage = \"\") : base(FormatMessage(errorCode, errorMessage))", NameSpace)
668+
w.Writeln(" {")
669+
w.Writeln(" _errorCode = errorCode;")
670+
w.Writeln(" _errorMessage = errorMessage;")
671+
w.Writeln(" }")
672+
w.Writeln("")
673+
w.Writeln(" /// <summary>")
674+
w.Writeln(" /// Gets the error code")
675+
w.Writeln(" /// </summary>")
676+
w.Writeln(" public int ErrorCode => _errorCode;")
677+
w.Writeln("")
678+
w.Writeln(" /// <summary>")
679+
w.Writeln(" /// Gets the custom error message")
680+
w.Writeln(" /// </summary>")
681+
w.Writeln(" public string ErrorMessage => _errorMessage;")
682+
w.Writeln("")
683+
w.Writeln(" /// <summary>")
684+
w.Writeln(" /// Gets the error name (constant name)")
685+
w.Writeln(" /// </summary>")
686+
w.Writeln(" public string ErrorName")
687+
w.Writeln(" {")
688+
w.Writeln(" get")
689+
w.Writeln(" {")
690+
w.Writeln(" switch (_errorCode)")
691+
w.Writeln(" {")
692+
w.Writeln(" case 0: return \"SUCCESS\";")
693+
for _, errorDef := range component.Errors.Errors {
694+
w.Writeln(" case %d: return \"%s\";", errorDef.Code, errorDef.Name)
695+
}
696+
w.Writeln(" default: return \"UNKNOWN\";")
697+
w.Writeln(" }")
698+
w.Writeln(" }")
699+
w.Writeln(" }")
700+
w.Writeln("")
701+
w.Writeln(" /// <summary>")
702+
w.Writeln(" /// Gets the error description (human-readable)")
703+
w.Writeln(" /// </summary>")
704+
w.Writeln(" public string ErrorDescription")
705+
w.Writeln(" {")
706+
w.Writeln(" get")
707+
w.Writeln(" {")
708+
w.Writeln(" switch (_errorCode)")
709+
w.Writeln(" {")
710+
w.Writeln(" case 0: return \"success\";")
711+
for _, errorDef := range component.Errors.Errors {
712+
w.Writeln(" case %d: return \"%s\";", errorDef.Code, errorDef.Description)
713+
}
714+
w.Writeln(" default: return \"unknown error\";")
715+
w.Writeln(" }")
716+
w.Writeln(" }")
717+
w.Writeln(" }")
718+
w.Writeln("")
719+
w.Writeln(" private static string FormatMessage(int errorCode, string errorMessage)")
720+
w.Writeln(" {")
721+
w.Writeln(" string errorName = GetErrorName(errorCode);")
722+
w.Writeln(" string errorDesc = GetErrorDescription(errorCode);")
723+
w.Writeln(" if (!string.IsNullOrEmpty(errorMessage))")
724+
w.Writeln(" return $\"E%sException {errorName} ({errorCode}): {errorDesc} - {errorMessage}\";", NameSpace)
725+
w.Writeln(" else")
726+
w.Writeln(" return $\"E%sException {errorName} ({errorCode}): {errorDesc}\";", NameSpace)
727+
w.Writeln(" }")
728+
w.Writeln("")
729+
w.Writeln(" private static string GetErrorName(int errorCode)")
730+
w.Writeln(" {")
731+
w.Writeln(" switch (errorCode)")
732+
w.Writeln(" {")
733+
w.Writeln(" case 0: return \"SUCCESS\";")
734+
for _, errorDef := range component.Errors.Errors {
735+
w.Writeln(" case %d: return \"%s\";", errorDef.Code, errorDef.Name)
736+
}
737+
w.Writeln(" default: return \"UNKNOWN\";")
738+
w.Writeln(" }")
739+
w.Writeln(" }")
740+
w.Writeln("")
741+
w.Writeln(" private static string GetErrorDescription(int errorCode)")
742+
w.Writeln(" {")
743+
w.Writeln(" switch (errorCode)")
744+
w.Writeln(" {")
745+
w.Writeln(" case 0: return \"success\";")
746+
for _, errorDef := range component.Errors.Errors {
747+
w.Writeln(" case %d: return \"%s\";", errorDef.Code, errorDef.Description)
748+
}
749+
w.Writeln(" default: return \"unknown error\";")
750+
w.Writeln(" }")
751+
w.Writeln(" }")
752+
w.Writeln(" }")
753+
w.Writeln("")
754+
653755
for i := 0; i < len(component.Enums); i++ {
654756
enum := component.Enums[i]
655757
w.Writeln(" public enum e%s {", enum.Name)
@@ -967,7 +1069,7 @@ func buildBindingCSharpImplementation(component ComponentDefinition, w LanguageW
9671069
w.Writeln(" }")
9681070
w.Writeln("")
9691071
}
970-
w.Writeln(" throw new Exception(sMessage + \"(# \" + errorCode + \")\");")
1072+
w.Writeln(" throw new E%sException(errorCode, sMessage);", NameSpace)
9711073
w.Writeln(" }")
9721074

9731075
w.Writeln("")

0 commit comments

Comments
 (0)