diff --git a/csharp/Platform.Data.Tests/ExceptionMessagesTests.cs b/csharp/Platform.Data.Tests/ExceptionMessagesTests.cs new file mode 100644 index 00000000..46dd3c40 --- /dev/null +++ b/csharp/Platform.Data.Tests/ExceptionMessagesTests.cs @@ -0,0 +1,247 @@ +using System; +using System.Globalization; +using System.Threading; +using Xunit; +using Platform.Data.Exceptions; +using Platform.Data.Resources; + +namespace Platform.Data.Tests +{ + /// + /// + /// Tests for internationalization of exception messages. + /// + /// + /// Тесты для интернационализации сообщений об ошибках. + /// + /// + public static class ExceptionMessagesTests + { + /// + /// + /// Tests that exception messages are localized correctly for English culture. + /// + /// + /// Тестирует, что сообщения об ошибках правильно локализуются для английской культуры. + /// + /// + [Fact] + public static void ExceptionMessagesInEnglish() + { + // Arrange + var originalCulture = CultureInfo.CurrentUICulture; + try + { + // Set culture to English + CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("en-US"); + + // Act & Assert - Test ArgumentLinkDoesNotExist messages + var linkDoesNotExistMessage = ExceptionMessages.ArgumentLinkDoesNotExist(123, "testArgument"); + Assert.Equal("Link [123] passed in argument [testArgument] does not exist.", linkDoesNotExistMessage); + + var linkDoesNotExistSimpleMessage = ExceptionMessages.ArgumentLinkDoesNotExistSimple(456); + Assert.Equal("Link [456] passed as argument does not exist.", linkDoesNotExistSimpleMessage); + + // Test ArgumentLinkHasDependencies messages + var linkHasDependenciesMessage = ExceptionMessages.ArgumentLinkHasDependencies(789, "testParam"); + Assert.Equal("Link [789] passed in argument [testParam] has dependencies that prevent modification of its internal structure.", linkHasDependenciesMessage); + + var linkHasDependenciesSimpleMessage = ExceptionMessages.ArgumentLinkHasDependenciesSimple(101); + Assert.Equal("Link [101] passed as argument has dependencies that prevent modification of its internal structure.", linkHasDependenciesSimpleMessage); + + // Test LinksLimitReached messages + var linksLimitReachedMessage = ExceptionMessages.LinksLimitReached(1000); + Assert.Equal("Links storage limit reached (1000).", linksLimitReachedMessage); + + var linksLimitReachedDefaultMessage = ExceptionMessages.LinksLimitReachedDefault; + Assert.Equal("Links storage limit reached.", linksLimitReachedDefaultMessage); + + // Test LinkWithSameValueAlreadyExists message + var linkWithSameValueMessage = ExceptionMessages.LinkWithSameValueAlreadyExists; + Assert.Equal("Link with same value already exists.", linkWithSameValueMessage); + } + finally + { + // Restore original culture + CultureInfo.CurrentUICulture = originalCulture; + } + } + + /// + /// + /// Tests that exception messages are localized correctly for Russian culture. + /// + /// + /// Тестирует, что сообщения об ошибках правильно локализуются для русской культуры. + /// + /// + [Fact] + public static void ExceptionMessagesInRussian() + { + // Arrange + var originalCulture = CultureInfo.CurrentUICulture; + try + { + // Set culture to Russian + CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("ru-RU"); + + // Act & Assert - Test ArgumentLinkDoesNotExist messages + var linkDoesNotExistMessage = ExceptionMessages.ArgumentLinkDoesNotExist(123, "testArgument"); + Assert.Equal("Связь [123] переданная в аргумент [testArgument] не существует.", linkDoesNotExistMessage); + + var linkDoesNotExistSimpleMessage = ExceptionMessages.ArgumentLinkDoesNotExistSimple(456); + Assert.Equal("Связь [456] переданная в качестве аргумента не существует.", linkDoesNotExistSimpleMessage); + + // Test ArgumentLinkHasDependencies messages + var linkHasDependenciesMessage = ExceptionMessages.ArgumentLinkHasDependencies(789, "testParam"); + Assert.Equal("У связи [789] переданной в аргумент [testParam] присутствуют зависимости, которые препятствуют изменению её внутренней структуры.", linkHasDependenciesMessage); + + var linkHasDependenciesSimpleMessage = ExceptionMessages.ArgumentLinkHasDependenciesSimple(101); + Assert.Equal("У связи [101] переданной в качестве аргумента присутствуют зависимости, которые препятствуют изменению её внутренней структуры.", linkHasDependenciesSimpleMessage); + + // Test LinksLimitReached messages + var linksLimitReachedMessage = ExceptionMessages.LinksLimitReached(1000); + Assert.Equal("Достигнут лимит количества связей в хранилище (1000).", linksLimitReachedMessage); + + var linksLimitReachedDefaultMessage = ExceptionMessages.LinksLimitReachedDefault; + Assert.Equal("Достигнут лимит количества связей в хранилище.", linksLimitReachedDefaultMessage); + + // Test LinkWithSameValueAlreadyExists message + var linkWithSameValueMessage = ExceptionMessages.LinkWithSameValueAlreadyExists; + Assert.Equal("Связь с таким же значением уже существует.", linkWithSameValueMessage); + } + finally + { + // Restore original culture + CultureInfo.CurrentUICulture = originalCulture; + } + } + + /// + /// + /// Tests that exception classes use localized messages correctly. + /// + /// + /// Тестирует, что классы исключений правильно используют локализованные сообщения. + /// + /// + [Fact] + public static void ExceptionClassesUseLocalizedMessages() + { + // Arrange + var originalCulture = CultureInfo.CurrentUICulture; + try + { + // Test with English culture + CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("en-US"); + + // Test ArgumentLinkDoesNotExistsException + var linkDoesNotExistException = new ArgumentLinkDoesNotExistsException(123, "testArg"); + Assert.Contains("Link [123] passed in argument [testArg] does not exist", linkDoesNotExistException.Message); + + var linkDoesNotExistSimpleException = new ArgumentLinkDoesNotExistsException(456); + Assert.Contains("Link [456] passed as argument does not exist", linkDoesNotExistSimpleException.Message); + + // Test ArgumentLinkHasDependenciesException + var linkHasDependenciesException = new ArgumentLinkHasDependenciesException(789, "testParam"); + Assert.Contains("Link [789] passed in argument [testParam] has dependencies", linkHasDependenciesException.Message); + + var linkHasDependenciesSimpleException = new ArgumentLinkHasDependenciesException(101); + Assert.Contains("Link [101] passed as argument has dependencies", linkHasDependenciesSimpleException.Message); + + // Test LinksLimitReachedException + var linksLimitException = new LinksLimitReachedException(1000); + Assert.Contains("Links storage limit reached (1000)", linksLimitException.Message); + + var linksLimitDefaultException = new LinksLimitReachedException(); + Assert.Contains("Links storage limit reached", linksLimitDefaultException.Message); + + // Test LinkWithSameValueAlreadyExistsException + var linkWithSameValueException = new LinkWithSameValueAlreadyExistsException(); + Assert.Contains("Link with same value already exists", linkWithSameValueException.Message); + + // Test with Russian culture + CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("ru-RU"); + + var linkDoesNotExistExceptionRu = new ArgumentLinkDoesNotExistsException(123, "testArg"); + Assert.Contains("Связь [123] переданная в аргумент [testArg] не существует", linkDoesNotExistExceptionRu.Message); + + var linksLimitExceptionRu = new LinksLimitReachedException(1000); + Assert.Contains("Достигнут лимит количества связей в хранилище (1000)", linksLimitExceptionRu.Message); + } + finally + { + // Restore original culture + CultureInfo.CurrentUICulture = originalCulture; + } + } + + /// + /// + /// Tests that default message properties are localized correctly. + /// + /// + /// Тестирует, что свойства сообщений по умолчанию правильно локализованы. + /// + /// + [Fact] + public static void DefaultMessagePropertiesAreLocalized() + { + // Arrange + var originalCulture = CultureInfo.CurrentUICulture; + try + { + // Test with English culture + CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("en-US"); + Assert.Equal("Links storage limit reached.", LinksLimitReachedExceptionBase.DefaultMessage); + Assert.Equal("Link with same value already exists.", LinkWithSameValueAlreadyExistsException.DefaultMessage); + + // Test with Russian culture + CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("ru-RU"); + Assert.Equal("Достигнут лимит количества связей в хранилище.", LinksLimitReachedExceptionBase.DefaultMessage); + Assert.Equal("Связь с таким же значением уже существует.", LinkWithSameValueAlreadyExistsException.DefaultMessage); + } + finally + { + // Restore original culture + CultureInfo.CurrentUICulture = originalCulture; + } + } + + /// + /// + /// Tests that localization works with different numeric types. + /// + /// + /// Тестирует, что локализация работает с различными числовыми типами. + /// + /// + [Fact] + public static void LocalizationWorksWithDifferentNumericTypes() + { + // Arrange + var originalCulture = CultureInfo.CurrentUICulture; + try + { + CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("en-US"); + + // Test with byte + var byteMessage = ExceptionMessages.ArgumentLinkDoesNotExistSimple(255); + Assert.Equal("Link [255] passed as argument does not exist.", byteMessage); + + // Test with uint + var uintMessage = ExceptionMessages.ArgumentLinkDoesNotExistSimple(4294967295); + Assert.Equal("Link [4294967295] passed as argument does not exist.", uintMessage); + + // Test with ulong + var ulongMessage = ExceptionMessages.LinksLimitReached(18446744073709551615); + Assert.Equal("Links storage limit reached (18446744073709551615).", ulongMessage); + } + finally + { + // Restore original culture + CultureInfo.CurrentUICulture = originalCulture; + } + } + } +} \ No newline at end of file diff --git a/csharp/Platform.Data/Exceptions/ArgumentLinkDoesNotExistsException.cs b/csharp/Platform.Data/Exceptions/ArgumentLinkDoesNotExistsException.cs index 7761f5ed..a9673990 100644 --- a/csharp/Platform.Data/Exceptions/ArgumentLinkDoesNotExistsException.cs +++ b/csharp/Platform.Data/Exceptions/ArgumentLinkDoesNotExistsException.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.CompilerServices; +using Platform.Data.Resources; #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member @@ -95,8 +96,8 @@ public ArgumentLinkDoesNotExistsException(string message) : base(message) { } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ArgumentLinkDoesNotExistsException() { } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static string FormatMessage(TLinkAddress link, string argumentName) => $"Связь [{link}] переданная в аргумент [{argumentName}] не существует."; + private static string FormatMessage(TLinkAddress link, string argumentName) => ExceptionMessages.ArgumentLinkDoesNotExist(link, argumentName); [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static string FormatMessage(TLinkAddress link) => $"Связь [{link}] переданная в качестве аргумента не существует."; + private static string FormatMessage(TLinkAddress link) => ExceptionMessages.ArgumentLinkDoesNotExistSimple(link); } } diff --git a/csharp/Platform.Data/Exceptions/ArgumentLinkHasDependenciesException.cs b/csharp/Platform.Data/Exceptions/ArgumentLinkHasDependenciesException.cs index 116b8742..22f27b66 100644 --- a/csharp/Platform.Data/Exceptions/ArgumentLinkHasDependenciesException.cs +++ b/csharp/Platform.Data/Exceptions/ArgumentLinkHasDependenciesException.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.CompilerServices; +using Platform.Data.Resources; #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member @@ -83,8 +84,8 @@ public ArgumentLinkHasDependenciesException(string message) : base(message) { } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ArgumentLinkHasDependenciesException() { } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static string FormatMessage(TLinkAddress link, string paramName) => $"У связи [{link}] переданной в аргумент [{paramName}] присутствуют зависимости, которые препятствуют изменению её внутренней структуры."; + private static string FormatMessage(TLinkAddress link, string paramName) => ExceptionMessages.ArgumentLinkHasDependencies(link, paramName); [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static string FormatMessage(TLinkAddress link) => $"У связи [{link}] переданной в качестве аргумента присутствуют зависимости, которые препятствуют изменению её внутренней структуры."; + private static string FormatMessage(TLinkAddress link) => ExceptionMessages.ArgumentLinkHasDependenciesSimple(link); } } diff --git a/csharp/Platform.Data/Exceptions/LinkWithSameValueAlreadyExistsException.cs b/csharp/Platform.Data/Exceptions/LinkWithSameValueAlreadyExistsException.cs index dba24c4c..58606a7b 100644 --- a/csharp/Platform.Data/Exceptions/LinkWithSameValueAlreadyExistsException.cs +++ b/csharp/Platform.Data/Exceptions/LinkWithSameValueAlreadyExistsException.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.CompilerServices; +using Platform.Data.Resources; #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member @@ -20,7 +21,7 @@ public class LinkWithSameValueAlreadyExistsException : Exception /// /// /// - public static readonly string DefaultMessage = "Связь с таким же значением уже существует."; + public static string DefaultMessage => ExceptionMessages.LinkWithSameValueAlreadyExists; /// /// diff --git a/csharp/Platform.Data/Exceptions/LinksLimitReachedException.cs b/csharp/Platform.Data/Exceptions/LinksLimitReachedException.cs index ddc2aaa0..de5fddeb 100644 --- a/csharp/Platform.Data/Exceptions/LinksLimitReachedException.cs +++ b/csharp/Platform.Data/Exceptions/LinksLimitReachedException.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.CompilerServices; +using Platform.Data.Resources; #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member @@ -66,6 +67,6 @@ public LinksLimitReachedException(string message) : base(message) { } [MethodImpl(MethodImplOptions.AggressiveInlining)] public LinksLimitReachedException() : base(DefaultMessage) { } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static string FormatMessage(TLinkAddress limit) => $"Достигнут лимит количества связей в хранилище ({limit})."; + private static string FormatMessage(TLinkAddress limit) => ExceptionMessages.LinksLimitReached(limit); } } diff --git a/csharp/Platform.Data/Exceptions/LinksLimitReachedExceptionBase.cs b/csharp/Platform.Data/Exceptions/LinksLimitReachedExceptionBase.cs index b4801fc3..eb665940 100644 --- a/csharp/Platform.Data/Exceptions/LinksLimitReachedExceptionBase.cs +++ b/csharp/Platform.Data/Exceptions/LinksLimitReachedExceptionBase.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.CompilerServices; +using Platform.Data.Resources; #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member @@ -20,7 +21,7 @@ public abstract class LinksLimitReachedExceptionBase : Exception /// /// /// - public static readonly string DefaultMessage = "Достигнут лимит количества связей в хранилище."; + public static string DefaultMessage => ExceptionMessages.LinksLimitReachedDefault; /// /// diff --git a/csharp/Platform.Data/Resources/ExceptionMessages.cs b/csharp/Platform.Data/Resources/ExceptionMessages.cs new file mode 100644 index 00000000..578ce607 --- /dev/null +++ b/csharp/Platform.Data/Resources/ExceptionMessages.cs @@ -0,0 +1,165 @@ +using System.Globalization; +using System.Resources; +using System.Runtime.CompilerServices; + +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member + +namespace Platform.Data.Resources +{ + /// + /// + /// Provides access to localized exception messages. + /// + /// + /// Обеспечивает доступ к локализованным сообщениям об ошибках. + /// + /// + public static class ExceptionMessages + { + private static readonly ResourceManager _resourceManager = new ResourceManager("Platform.Data.Resources.ExceptionMessages", typeof(ExceptionMessages).Assembly); + + /// + /// + /// Gets the formatted message for an argument link that does not exist. + /// + /// + /// Получает отформатированное сообщение для аргумента связи, которая не существует. + /// + /// + /// + /// The link identifier. + /// Идентификатор связи. + /// + /// + /// The argument name. + /// Имя аргумента. + /// + /// + /// The formatted localized message. + /// Отформатированное локализованное сообщение. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string ArgumentLinkDoesNotExist(TLinkAddress link, string argumentName) + { + return string.Format(GetString("ArgumentLinkDoesNotExist"), link, argumentName); + } + + /// + /// + /// Gets the formatted message for an argument link that does not exist (simple version). + /// + /// + /// Получает отформатированное сообщение для аргумента связи, которая не существует (упрощенная версия). + /// + /// + /// + /// The link identifier. + /// Идентификатор связи. + /// + /// + /// The formatted localized message. + /// Отформатированное локализованное сообщение. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string ArgumentLinkDoesNotExistSimple(TLinkAddress link) + { + return string.Format(GetString("ArgumentLinkDoesNotExistSimple"), link); + } + + /// + /// + /// Gets the formatted message for an argument link that has dependencies. + /// + /// + /// Получает отформатированное сообщение для аргумента связи, которая имеет зависимости. + /// + /// + /// + /// The link identifier. + /// Идентификатор связи. + /// + /// + /// The parameter name. + /// Имя параметра. + /// + /// + /// The formatted localized message. + /// Отформатированное локализованное сообщение. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string ArgumentLinkHasDependencies(TLinkAddress link, string paramName) + { + return string.Format(GetString("ArgumentLinkHasDependencies"), link, paramName); + } + + /// + /// + /// Gets the formatted message for an argument link that has dependencies (simple version). + /// + /// + /// Получает отформатированное сообщение для аргумента связи, которая имеет зависимости (упрощенная версия). + /// + /// + /// + /// The link identifier. + /// Идентификатор связи. + /// + /// + /// The formatted localized message. + /// Отформатированное локализованное сообщение. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string ArgumentLinkHasDependenciesSimple(TLinkAddress link) + { + return string.Format(GetString("ArgumentLinkHasDependenciesSimple"), link); + } + + /// + /// + /// Gets the formatted message for when links limit is reached. + /// + /// + /// Получает отформатированное сообщение о достижении лимита связей. + /// + /// + /// + /// The limit value. + /// Значение лимита. + /// + /// + /// The formatted localized message. + /// Отформатированное локализованное сообщение. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string LinksLimitReached(TLinkAddress limit) + { + return string.Format(GetString("LinksLimitReached"), limit); + } + + /// + /// + /// Gets the default message for when links limit is reached. + /// + /// + /// Получает сообщение по умолчанию о достижении лимита связей. + /// + /// + public static string LinksLimitReachedDefault => GetString("LinksLimitReachedDefault"); + + /// + /// + /// Gets the message for when a link with same value already exists. + /// + /// + /// Получает сообщение о том, что связь с таким же значением уже существует. + /// + /// + public static string LinkWithSameValueAlreadyExists => GetString("LinkWithSameValueAlreadyExists"); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static string GetString(string name) + { + return _resourceManager.GetString(name, CultureInfo.CurrentUICulture) ?? name; + } + } +} \ No newline at end of file diff --git a/csharp/Platform.Data/Resources/ExceptionMessages.resx b/csharp/Platform.Data/Resources/ExceptionMessages.resx new file mode 100644 index 00000000..886e16f2 --- /dev/null +++ b/csharp/Platform.Data/Resources/ExceptionMessages.resx @@ -0,0 +1,73 @@ + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Link [{0}] passed in argument [{1}] does not exist. + + + Link [{0}] passed as argument does not exist. + + + Link [{0}] passed in argument [{1}] has dependencies that prevent modification of its internal structure. + + + Link [{0}] passed as argument has dependencies that prevent modification of its internal structure. + + + Links storage limit reached ({0}). + + + Links storage limit reached. + + + Link with same value already exists. + + \ No newline at end of file diff --git a/csharp/Platform.Data/Resources/ExceptionMessages.ru.resx b/csharp/Platform.Data/Resources/ExceptionMessages.ru.resx new file mode 100644 index 00000000..954de628 --- /dev/null +++ b/csharp/Platform.Data/Resources/ExceptionMessages.ru.resx @@ -0,0 +1,73 @@ + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Связь [{0}] переданная в аргумент [{1}] не существует. + + + Связь [{0}] переданная в качестве аргумента не существует. + + + У связи [{0}] переданной в аргумент [{1}] присутствуют зависимости, которые препятствуют изменению её внутренней структуры. + + + У связи [{0}] переданной в качестве аргумента присутствуют зависимости, которые препятствуют изменению её внутренней структуры. + + + Достигнут лимит количества связей в хранилище ({0}). + + + Достигнут лимит количества связей в хранилище. + + + Связь с таким же значением уже существует. + + \ No newline at end of file diff --git a/examples/InternationalizationDemo.cs b/examples/InternationalizationDemo.cs new file mode 100644 index 00000000..283bb676 --- /dev/null +++ b/examples/InternationalizationDemo.cs @@ -0,0 +1,71 @@ +using System; +using System.Globalization; +using Platform.Data.Exceptions; + +/// +/// Demonstrates the internationalization functionality of exception messages. +/// This shows how exception messages are now properly localized based on the current culture. +/// +class Program +{ + static void Main(string[] args) + { + Console.WriteLine("=== Platform.Data Exception Internationalization Demo ===\n"); + + // Test with English (default) culture + Console.WriteLine("--- English (en-US) Culture ---"); + CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("en-US"); + DemonstrateExceptions(); + + Console.WriteLine("\n--- Russian (ru-RU) Culture ---"); + CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("ru-RU"); + DemonstrateExceptions(); + + Console.WriteLine("\n--- Switching back to English ---"); + CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo("en-US"); + DemonstrateExceptions(); + } + + static void DemonstrateExceptions() + { + try + { + // ArgumentLinkDoesNotExistsException + throw new ArgumentLinkDoesNotExistsException(123, "testArgument"); + } + catch (ArgumentLinkDoesNotExistsException ex) + { + Console.WriteLine($"ArgumentLinkDoesNotExistsException: {ex.Message}"); + } + + try + { + // ArgumentLinkHasDependenciesException + throw new ArgumentLinkHasDependenciesException(456, "linkParam"); + } + catch (ArgumentLinkHasDependenciesException ex) + { + Console.WriteLine($"ArgumentLinkHasDependenciesException: {ex.Message}"); + } + + try + { + // LinksLimitReachedException + throw new LinksLimitReachedException(1000000); + } + catch (LinksLimitReachedException ex) + { + Console.WriteLine($"LinksLimitReachedException: {ex.Message}"); + } + + try + { + // LinkWithSameValueAlreadyExistsException + throw new LinkWithSameValueAlreadyExistsException(); + } + catch (LinkWithSameValueAlreadyExistsException ex) + { + Console.WriteLine($"LinkWithSameValueAlreadyExistsException: {ex.Message}"); + } + } +} \ No newline at end of file