Когда я работал над проектом, я подумал про себя: «Хм, было бы очень удобно зарегистрировать сообщение, а затем выдать исключение с тем же сообщением».Так как это позволило бы мне придерживаться принципа «исключения - для исключительных обстоятельств», но все же следить за тем, чтобы мы записывали подробную информацию о том, что пошло не так в системе.
Итак, что привело к:
public static class LogAndThrow
{
public static void Message<TException>(string message) where TException : Exception
{
// Log message here
var constructor =
typeof(TException).GetConstructor(new[] { typeof(string) });
throw (TException)constructor.Invoke(new[] { message });
}
}
Конечно, это немного грубо (и я сократил это для этого поста), но это работает.
Несмотря на то, что я являюсь типом людей, создающих исключения через отражение, я был раздражен, что трассировка стекабудет "испорчен" строкой LogAndThrow.Message ().
Поэтому я решил исправить это: -)
Мне удалось заменить трассировку стека некоторой сериализацией и другими хитростямиВсе очень глупо и грубо.Но я хотел выяснить это только потому, что.
Но я заметил кое-что любопытное:
var exception = new Exception();
throw exception;
После того, как это исключение создано, но до того, как оно выброшено, единственное, что устанавливается, - это Сообщение.,Трассировка стека и т. Д. Являются пустыми.
Вышесказанное эквивалентно следующему IL:
.locals init (
[0] class [mscorlib]System.Exception exception)
nop
newobj instance void [mscorlib]System.Exception::.ctor()
stloc.0
ldloc.0
throw
Что мне кажется, что IL для 'throw' делает нечто большее, чем просто принятие этогоссылаться и подниматься по стеку.
Кто-нибудь знает, что делает среда выполнения с исключением в стеке, когда достигается IL 'throw'?
Трюк, который мы использовали ниже, чтобы изменитьстек относится к этой "магии" в броске, я думаю:
Этот код ужасен и неправильн.Больше научного эксперимента, чем что-либо, что когда-либо должно быть запущено в производство. Eververver EVER
var e = new Exception("message here");
try
{
throw e;
}
finally
{
// Get the private file _stackTraceString with reflection
field.SetValue(e, new StackTrace(1).ToString());
}