Возврат информации с пользовательскими исключениями C#
У меня есть следующая проблема:
-
У меня есть метод обслуживания:
public bool EmployeeCanReiceivePayment(int employeeId) { ... int workingHours = this.GetEmployeeWorkingHours(employeeId); if(workingHours < N) { throw new EmployeeCannotReceivePaymentException(); } return true; } public int GetEmployeeWorkingHours(int employeeId) { //returns the number of working hours of the employee for the last month }
Вопрос в следующем:
Есть ли способ возвращает объект или дополнительную информацию с моим пользовательским исключением. А под дополнительной информацией я подразумеваю объект или просто несколько параметров.
2 ответа:
Избегайте использования исключений для потока управления
Это правило использования .NET Framework
DA0007: избегайте использования исключений для потока управления
Использование обработчика исключений в рамках регулярного выполнения программы логика может быть дорогостоящей, и ее следует избегать. В большинстве случаев, исключения должны использоваться только для обстоятельств, которые происходят нечасто и не ожидаются..
Вместо создания исключения создайте класс которая будет содержать всю необходимую информацию.
public class PaymentValidation { public bool IsValid { get; set;} public YourType SomeAdditionalInformation { get; set;} } public PaymentValidation EmployeeCanReiceivePayment(int employeeId) { int workingHours = this.GetEmployeeWorkingHours(employeeId); var validationResult = new PaymentValidation(); validationResult.IsValid = true; if(workingHours < N) { validationResult.IsValid = false; } return validationResult; }
Возвращение собственного типа даст больше возможностей для дальнейших изменений.
Например, создайте интерфейс, который представляет возвращаемый тип. И создайте собственную реализацию для каждого случая, который у вас есть
public interface IPayment { void Pay(); }
Реализовать интерфейсы для каждого случая
public class NotEnoughWorkingHoursPayment : IPayment { public void Pay() { //Do nothing or log failed payment or inform user about it } } public class SuccesfullPayment : IPayment { public void Pay() { //Execute payment } } public class PaymentService { public IPayment ValidatePayment() { const int MIN_WORKING_HOURS = 40; int workingHours = this.GetEmployeeWorkingHours(employeeId); if(workingHourse < MIN_WORKING_HOURS) { return New NotEnoughWorkingHoursPayment(); } return new SuccesfullPayment(); } }
Тогда использование будет очень простым и понятным
IPayment payment = paymentService.ValidatePayment(); payment.Pay();
Я согласен с тем, что другие говорят здесь, что принуждение вашего BL исключениями не является хорошей практикой. Вместо исключения вы можете вернуть "ResultObject", который содержит статус успеха + сведения и допустимые возвращаемые данные.
Но если вы решите сделать это, то настройте свое пользовательское исключение, чтобы включить в него не только конструктор по умолчанию. Они такие же, как и любой другой класс. Что-то вроде:
public class MyCustomException : Exception { //This is like you have now public MyCustomException() { } //This is if you want to have different messages public MyCustomException(string message) : base(message{ } //This is if you want to have different data to add (don't use object but a custom type public MyCustomException(object yourObject) { YourObject = yourObject; } public object YourObject { get; set; } }
В вашем сценарии тогда, вероятно, что-то вроде:
public class EmployeeException : Exception { ... } //Add what you need from the example above //Then when needed: new EmployeeException("some text for this error"); new EmployeeException("some other text for this error"); //Or when with a proper object to describe more details: new EmployeeException(new NotEnoughHours { ... });