プライベートフィールドを取得または設定することは可能ですか?
私は手に入れたい System.Guid.c
。これにアクセスする方法はありますか、またはStrutからコードをコピーしてフィールドをパブリックにする必要がありますか?
Quanticプログラミングで提案されているリフレクションを使用できます
var guid = Guid.NewGuid();
var field= typeof (Guid).GetField("_c", BindingFlags.NonPublic |BindingFlags.GetField | BindingFlags.Instance);
var value = field.GetValue(guid);
最初にguidをバイト配列に変換することに問題がない場合は、次のことをお勧めします。
var guid = Guid.NewGuid();
var c = BitConverter.ToInt16(guid.ToByteArray(), 6);
後者の方法では、リフレクションの使用を避けます。
編集
値も設定できるようにする必要があると述べても、リフレクションを回避できます。
var guid = Guid.NewGuid();
var guidBytes = guid.ToByteArray();
// get value
var c = BitConverter.ToInt16(guidBytes, 6);
// set value
Buffer.BlockCopy(BitConverter.GetBytes(c), 0, guidBytes, 6, sizeof(Int16));
var modifiedGuid = new Guid(guidBytes);
System.Reflection を試してみてください。次に例を示します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace AccessPrivateField
{
class foo
{
public foo(string str)
{
this.str = str;
}
private string str;
public string Get()
{
return this.str;
}
}
class Program
{
static void Main(string[] args)
{
foo bar = new foo("hello");
Console.WriteLine(bar.Get());
typeof(foo).GetField("str", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(bar, "changed");
Console.WriteLine(bar.Get());
//output:
//hello
//changed
}
}
}
これをリフレクションで行うことは可能ですが、System.Guid.ToByteArray()
からc
を取得する方が簡単な場合があります。
byte[] guid = guid.ToByteArray();
short c = (short)((guid[7] << 8) | guid[6]);
このアプローチは公開され文書化されたメソッドを使用するため、バージョン間での変更の影響を受けにくくなります。 (一般に、プライベート実装の詳細に依存することは避けてください。これらの詳細はバージョンごとに変更される可能性があるためです。)
拡張メソッドを使用して、任意のタイプの任意のプライベートフィールドを取得できます。
public static T GetFieldValue<T>(this object obj, string name) {
var field = obj.GetType().GetField(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
return (T)field?.GetValue(obj);
}
次に、任意のタイプのプライベートフィールドにアクセスします。
Guid id = Guid.NewGuid();
Int16 c = id.GetFieldValue<Int16>("_c");