121

リフレクションを使用して多くのことができるので、コンストラクターの実行が完了した後にプライベート読み取り専用フィールドを変更できますか?
(注:ただの好奇心)

public class Foo
{
 private readonly int bar;

 public Foo(int num)
 {
  bar = num;
 }

 public int GetBar()
 {
  return bar;
 }
}

Foo foo = new Foo(123);
Console.WriteLine(foo.GetBar()); // display 123
// reflection code here...
Console.WriteLine(foo.GetBar()); // display 456
4

8 に答える 8

160

あなたはできる:

typeof(Foo)
   .GetField("bar",BindingFlags.Instance|BindingFlags.NonPublic)
   .SetValue(foo,567);
于 2009-06-01T13:59:10.610 に答える
54

明らかなことは、それを試すことです:

using System;
using System.Reflection;

public class Test
{
    private readonly string foo = "Foo";

    public static void Main()
    {
        Test test = new Test();
        FieldInfo field = typeof(Test).GetField
            ("foo", BindingFlags.Instance | BindingFlags.NonPublic);
        field.SetValue(test, "Hello");
        Console.WriteLine(test.foo);
    }        
}

これはうまくいきます。(興味深いことに、Java にはさまざまなルールがFieldあります。アクセスできるように明示的に設定する必要があり、とにかくインスタンス フィールドに対してのみ機能します。)

于 2009-06-01T13:59:56.630 に答える
11

一般的に機能するという点で他の回答に同意します。特に、これは文書化された動作ではないため、将来性のあるコードではないという E. Lippert のコメントに同意します。

ただし、別の問題にも気付きました。アクセス許可が制限された環境でコードを実行している場合、例外が発生する可能性があります。

私たちのコードが私たちのマシンで正常に動作するケースがありましたがVerificationException、コードが制限された環境で実行されたときにエラーが発生しました. 犯人は、読み取り専用フィールドのセッターへのリフレクション呼び出しでした。そのフィールドの読み取り専用制限を削除すると機能しました。

于 2013-02-26T11:36:19.330 に答える
4

これをしないでください。

オブジェクトが独自に宣言された型ではない可能性があるという超現実的なバグを修正するのに 1 日を費やしました。

読み取り専用フィールドを変更すると、一度は機能しました。しかし、もう一度変更しようとすると、次のような状況になります。

SoundDef mySound = Reflection_Modified_Readonly_SoundDef_Field;
if( !(mySound is SoundDef) )
    Log("Welcome to impossible-land!"); //This would run

だからやらないでください。

これは Mono ランタイム (Unity ゲーム エンジン) でした。

于 2014-05-12T17:52:33.707 に答える
4

なぜそのようなカプセル化を解除したいのかと尋ねました。

エンティティ ヘルパー クラスを使用してエンティティをハイドレートします。これは、リフレクションを使用して新しい空のエンティティのすべてのプロパティを取得し、プロパティ/フィールド名を結果セットの列に一致させ、propertyinfo.setvalue() を使用して設定します。

他の誰かが値を変更できるようにしたくありませんが、すべてのエンティティのハイドレーション メソッドをカスタマイズするために全力を尽くしたくもありません。

私のストアド プロシージャの多くは、テーブルやビューに直接対応しない結果セットを返すため、コード生成 ORM は何もしません。

于 2010-01-27T21:20:41.327 に答える
2

答えはイエスですが、もっと重要なことは次のとおりです。

なぜあなたはしたいですか?意図的にカプセル化を破ることは、私には恐ろしく悪い考えのように思えます。

リフレクションを使用して読み取り専用フィールドまたは定数フィールドを変更することは、意図しない結果の法則とマーフィーの法則を組み合わせたようなものです。

于 2009-06-01T14:21:04.950 に答える
0

単体テストのためにこのようなことを行う必要がある場合は、次を使用できることを追加したいだけです。

A) PrivateObjectクラス

B) まだ PrivateObject インスタンスが必要ですが、Visual Studio で「アクセサ」オブジェクトを生成できます。 方法: プライベート アクセサーを再生成する

ユニットテスト以外のコードでオブジェクトのプライベートフィールドを設定している場合、それは「コードの匂い」のインスタンスになるでしょう。おそらく、これを行いたい他の唯一の理由は、サードパーティを扱っている場合だと思いますライブラリであり、ターゲット クラス コードを変更することはできません。それでも、サードパーティに連絡して状況を説明し、サードパーティが先に進まないかどうかを確認し、必要に応じてコードを変更することをお勧めします。

于 2013-05-24T14:40:00.003 に答える