オブジェクトのコンストラクターにいるときに、InnerException
オブジェクトのException
プロパティを設定するにはどうすればよいですか?つまり、セッターを持たないプロパティのバッキングフィールドを見つけて設定することになります。
ところで、私はこれを見ました evain.net-Reflectionを使用してプロパティをバッキングするフィールドを取得する ですが、可能であれば、非ILベースのソリューションを探しています。
Exception
のコンストラクターはException
タイプが作成される場所なので、基本クラスコンストラクターMyException() :base(...)
などを使用して呼び出すことはできません。
なぜInnerExceptionをパラメータとしてコンストラクタを呼び出せないのですか?何らかの理由でそれが不可能な場合、System.Exceptionのバッキングフィールドは次のようになります。
private Exception _innerException;
Redgateのリフレクター を使用してそれを見つけました。リフレクションを使用すると、内部例外を設定できると思います。
編集:ほとんどの場合、リフレクションを介してプライベートフィールドにアクセスすることはお勧めできませんが、NTのケースについて十分に知らないため、それは良いか悪い考えです。
基本の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) {...}
Exception
クラスには、内部例外をパラメーターとして受け入れるオーバーロードされたコンストラクターがあります。
Exception exc = new Exception("message", new Exception("inner message"));
これはあなたが探しているものですか?
Exception exceptionWithMoreInfo = new Exception("extra info", ex);
バブルが発生する前に情報を追加したい例外をトラップしたと想定すると、通常の方法になります。
私があなたの質問を理解したら、あなたはこのようなことをしたいです:
Exception ex = new Exception("test");
Exception innerEx = new Exception("inner");
ex.GetType().GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(ex, innerEx);
Exceptionから継承するオブジェクトのコンストラクターにいる場合は、最初のthis
の代わりにex
を使用します。
ただし、これは、処理しようとしているものを処理するための最良の方法ではない場合があります。
Redgateのリフレクターを使用してフィールドを見つけます。例外の実装が変わることはないと思います...しかし、それはリスクです!
Exception(string, Exception)
コンストラクターを使用する場合、InnerException
を設定する必要はありませんか?これを変更できないのは設計上の理由によると思いますが、構築時には常に適切なコンストラクターに従うことができます。
class MyException : Exception {
public MyException()
: base("foo", new Exception("bar"))
{
...
}
...
}
私はコードの例外チェーンを壊すべきではないと思います。これは通常、二度と見つからないエラーにつながるからです。
私の状況では、このコードを使用しました:
class Foo
{
void Bar(MyException myException = null)
{
try
{
SomeActions.Invoke();
}
catch (Exception ex)
{
if (myException != null)
{
// Here I regenerate my exception with a new InnerException
var regenMyException = (MyException)System.Activator.CreateInstance(myException.GetType(), myException.Message, ex);
throw regenMyException;
}
throw new FooBarException("Exception on Foo.Bar()", ex);
}
}
}
HTH誰か;).
私は本当にパーティーに遅れていることを知っていますが、これはうまくいくことがわかりました。
public class MyException: Exception
{
public void SetInnerException(Exception exception)
{
typeof(Exception)
.GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(this, exception);
}
}
コツは、実際のException
タイプの_innerException
フィールドを取得してから、内部例外値をクラスインスタンス(この場合はMyException
)に設定することです。
これは変数に対しても機能します。
Exception mainException = new Exception();
typeof(Exception)
.GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(mainException , new Exception("Something bad happened!"));