¿Es posible obtener o establecer campos privados?Acceso a campos privados
Quiero obtener System.Guid.c
. ¿Hay alguna manera de acceder a él o debería simplemente copiar el código del puntal y hacer que los campos sean públicos?
¿Es posible obtener o establecer campos privados?Acceso a campos privados
Quiero obtener System.Guid.c
. ¿Hay alguna manera de acceder a él o debería simplemente copiar el código del puntal y hacer que los campos sean públicos?
Puede utilizar la reflexión según lo sugerido por Quantic Programación
var guid = Guid.NewGuid();
var field= typeof (Guid).GetField("_c", BindingFlags.NonPublic |BindingFlags.GetField | BindingFlags.Instance);
var value = field.GetValue(guid);
Aunque si estás bien con convirtiendo en primer lugar el GUID a una matriz de bytes, lo que podría sugerir:
var guid = Guid.NewGuid();
var c = BitConverter.ToInt16(guid.ToByteArray(), 6);
El último enfoque evita el uso de la reflexión.
Editar
usted menciona la necesidad de ser capaz de establecer el valor, así, todavía se puede evitar la reflexión:
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);
Gracias, creo que usará el primero a menos que haya un uso negativo de la reflexión. – godzcheater
@godzcheater - como lo menciona drf, el uso de la reflexión para acceder a miembros privados generalmente es una mala práctica. Está utilizando las partes internas de una clase para acceder a los datos. Siempre que sea posible, siempre debe intentar apegarse a la API pública. La reflexión de los miembros privados requerirá un entorno de confianza total y tiene el potencial de ser un código frágil, ya que los aspectos internos de la clase pueden cambiar con el tiempo. –
Deberías probar System.Reflection. He aquí un ejemplo:
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
}
}
}
Solo tenga en cuenta que si está ejecutando Silverlight, no podrá acceder a los miembros privados. No especificó que lo era, pero por las dudas. –
¿Por qué no? ¿Quiere decir que no puede acceder a los datos internos de Silverlight o no puede hacerlo cuando está bajo Silverlight? –
Con Silverlight, el tiempo de ejecución le impide acceder a datos no públicos mediante la reflexión, ya que es un problema de seguridad. Por ejemplo, parte del código de E/S del archivo está en el tiempo de ejecución, pero normalmente solo puede acceder a él a través de medios especiales y administrados que no violan las preocupaciones de seguridad. Si pudieras usar el reflejo para llegar a la esencia de la E/S de archivos ocultos, entonces con solo navegar a una página maliciosa de Silverlight podrías borrar/leer los archivos de tu computadora a voluntad. –
Si bien es posible hacer esto con la reflexión, puede ser más fácil simplemente recuperar c
desde System.Guid.ToByteArray()
.
byte[] guid = guid.ToByteArray();
short c = (short)((guid[7] << 8) | guid[6]);
Dado que este enfoque utiliza métodos públicos y documentados, está menos sujeto a cambios entre versiones. (En general, basándose en los detalles de implementación privados debe ser evitado, ya que estos detalles pueden cambiar de una versión a otra.)
Gracias, pero también necesito poder establecer el valor. – godzcheater
Usted puede tener un método de extensión para obtener cualquier campo privado de cualquier tipo:
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);
}
y luego acceder a un campo privado de un tipo arbitrario:
Guid id = Guid.NewGuid();
Int16 c = id.GetFieldValue<Int16>("_c");
su una pasta privada –
lo cambió, pero su justo System.Guid de todos modos. – godzcheater
posible duplicado de [¿Encontrar un campo privado con Reflection?] (Http://stackoverflow.com/questions/95910/find-a-private-field-with-reflection) –