Как установить InnerException пользовательского Класса исключений от его конструктора

Как я могу установить InnerException свойство Exception объект, в то время как я нахожусь в конструкторе того объекта? Это сводится к нахождению и установке отступающего поля свойства, которое не имеет никакого метода set.

BTW: Я видел этот evain.net - Получение поля, поддерживающего свойство с помощью Отражения, но ища не основанное на IL решение, если это возможно.

Конструктор Exception место где Exception тип создается, таким образом, я не могу назвать его с помощью конструктора базового класса MyException() :base(...) и т.д.

43
задан Shekhar 5 November 2019 в 18:18
поделиться

7 ответов

Почему нельзя просто вызвать конструктор, взяв InnerException в качестве параметра? Если по какой-то причине это невозможно, поддерживающее поле в System.Exception:

private Exception _innerException;

Я обнаружил это с помощью Reflector Redgate . Используя отражение, я полагаю, вы могли бы установить внутреннее исключение.

Edit: В большинстве случаев не рекомендуется получать доступ к закрытым полям через отражение, но я недостаточно знаю о случае NT, чтобы точно знать, если это хорошая или плохая идея.

13
ответ дан 26 November 2019 в 22:26
поделиться

Вы устанавливаете внутреннее исключение, вызывая базовый ctor:

public MyException(string message, Exception innerException)
       : base(message, innerException) {...}

Если вам нужно запустить некоторый код для получения исключения, используйте статический метод:

public MyException(SomeData data) : base(GetMessage(data), GetInner(data)) {...}
static Exception GetInner(SomeData data) {...} // <===== your type creation here!
static string GetMessage(SomeData data) {...}
83
ответ дан 26 November 2019 в 22:26
поделиться

Класс Exception имеет перегруженный конструктор, принимающий внутреннее исключение в качестве параметра:

Exception exc = new Exception("message", new Exception("inner message"));

Это то, что вы ищете?

40
ответ дан 26 November 2019 в 22:26
поделиться
Exception exceptionWithMoreInfo = new Exception("extra info", ex);

было бы нормальной практикой, если бы вы перехватили исключение, для которого вы хотите добавить дополнительную информацию, прежде чем всплыть.

8
ответ дан 26 November 2019 в 22:26
поделиться

Если я понимаю ваш вопрос, вы хотите сделать что-то вроде этого:

Exception ex = new Exception("test");
Exception innerEx = new Exception("inner");
ex.GetType().GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(ex, innerEx);

Если вы находитесь в конструкторе объекта, который наследуется от Exception, вы должны использовать this вместо из первого ex .

Но, возможно, это не лучший способ справиться с тем, с чем вы пытаетесь справиться.

2
ответ дан 26 November 2019 в 22:26
поделиться

Разве InnerException не должно быть установлено при использовании конструктора Exception (string, Exception) ? Я думаю, что вы не можете изменить это по умолчанию, но вы всегда можете обратиться к соответствующему конструктору во время создания:

class MyException : Exception {
    public MyException()
        : base("foo", new Exception("bar"))
    {
        ...
    }

    ...
}

Я думаю, вы никогда не должны нарушать цепочку исключений в своем коде, поскольку это обычно приводит к ошибкам, которые вы больше никогда не найду.

1
ответ дан 26 November 2019 в 22:26
поделиться

Используйте Отражатель Редгейта, чтобы найти поле. Я сомневаюсь, что реализация Exception когда-нибудь изменится ... Но это риск!

1
ответ дан 26 November 2019 в 22:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: