Définir InnerException of.NET objet D'Exception
Comment puis-je définir la propriété InnerException
d'un objet Exception
, alors que je suis dans le constructeur de cet objet? Cela se résume à trouver et à définir le champ de sauvegarde d'une propriété qui n'a pas de setter.
Btw: j'ai vu ceci (http://evain.net/blog/articles/2009/05/01/getting-the-field-backing-a-property-using-reflection) mais à la recherche d'une solution non basée sur IL, si possible.
Le constructeur D'Exception est l'endroit où le type D'Exception est créé, donc je ne peux pas l'appeler utilisation du constructeur de classe de base MyException (): base(...) etc.
8 réponses
Pourquoi ne pouvez-vous pas simplement appeler le constructeur en prenant L'InnerException comme paramètre? Si pour une raison quelconque ce n'est pas possible, le champ de sauvegarde dans le système.L'Exception est:
private Exception _innerException;
Je l'ai découvert en utilisant le réflecteur de Redgate . En utilisant la réflexion, je suppose que vous pouvez définir l'exception interne.
Edit: dans la plupart des cas, ce n'est pas une bonne idée d'accéder aux champs privés via la réflexion, mais je n'en sais pas assez sur le cas de NT pour savoir avec certitude si c'est une bonne ou une mauvaise idée.
Vous définissez l'exception interne en appelant le ctor de base:
public MyException(string message, Exception innerException)
: base(message, innerException) {...}
Si vous avez besoin d'exécuter du code pour obtenir l'exception, utilisez une méthode statique:
public MyException(SomeData data) : base(GetMessage(data), GetInner(data)) {...}
static Exception GetInner(SomeData data) {...} // <===== your type creation here!
static string GetMessage(SomeData data) {...}
La classe Exception
a un constructeur surchargé acceptant l'exception interne en tant que paramètre:
Exception exc = new Exception("message", new Exception("inner message"));
Est-ce ce que vous recherchez?
Exception exceptionWithMoreInfo = new Exception("extra info", ex);
Serait une pratique normale en supposant que vous avez piégé une exception à laquelle vous souhaitez ajouter plus d'informations avant de bouillonner.
InnerException
n'est-il pas censé être défini lors de l'utilisation du constructeur Exception(string, Exception)
? Je pense que c'est par conception que vous ne pouvez pas changer cela sinon, mais vous pouvez toujours vous en remettre au constructeur approprié au moment de la construction:
class MyException : Exception {
public MyException()
: base("foo", new Exception("bar"))
{
...
}
...
}
Je pense que vous ne devriez jamais casser la chaîne d'exception dans votre code car cela conduit généralement à des erreurs que vous ne retrouverez jamais.
Si je comprends votre question, vous voulez faire quelque chose comme ceci:
Exception ex = new Exception("test");
Exception innerEx = new Exception("inner");
ex.GetType().GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(ex, innerEx);
Si vous êtes dans le constructeur d'un objet qui hérite D'Exception, vous utiliseriez this
au lieu du premier ex
.
Mais ce n'est peut-être pas la meilleure façon de gérer ce que vous essayez de gérer.
Utilisez le réflecteur de Redgate pour trouver le champ. Je doute que la mise en œuvre de L'exception changera jamais... Mais c'est un risque!
Je sais que je suis vraiment en retard à la fête, mais je trouve que cela fonctionne.
public class MyException: Exception
{
public void SetInnerException(Exception exception)
{
typeof(Exception)
.GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(this, exception);
}
}
L'astuce consiste à obtenir le champ _innerException
du type Exception
réel, puis à définir la valeur de l'exception interne sur votre instance de classe (MyException
dans ce cas).
Cela fonctionne également pour les variables.
Exception mainException = new Exception();
typeof(Exception)
.GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(mainException , new Exception("Something bad happened!"));