2012-06-02 22 views
17

Özel alanlar almak veya ayarlamak mümkün müdür?Özel alanlara erişim

System.Guid.c'u almak istiyorum. Erişim yapmanın bir yolu var mı, yoksa kodu sadece diktatörden kopyalayıp alanları kamusallaştırmalı mıyım?

+0

onun özel macun –

+0

bunu değişti, ancak onun sadece yine System.Guid. – godzcheater

+1

olası bir kopyası [Yansıma ile özel bir alan bul?] (Http://stackoverflow.com/questions/95910/find-a-private-field-with-reflection) –

cevap

24

Quantic Programlama önerdiği gibi yansıma kullanabilirsiniz

var guid = Guid.NewGuid(); 
var field= typeof (Guid).GetField("_c", BindingFlags.NonPublic |BindingFlags.GetField | BindingFlags.Instance); 
var value = field.GetValue(guid); 

önce bir bayt dizisi guid dönüştürülmesi ile Tamam, ben önerilerde bulunsa:

var guid = Guid.NewGuid(); 
var c = BitConverter.ToInt16(guid.ToByteArray(), 6); 

Bu yaklaşım, yansımayı kullanmaktan kaçınır. o yansıma ile bunu yapmak mümkün olsa

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); 
+0

Teşekkürler, yansıma kullanmanın olumsuz bir tarafı olmadığı sürece ilkini kullanacağını düşünüyorum. – godzcheater

+3

@godzcheater - drf tarafından belirtildiği gibi, özel üyelere erişim için yansıma kullanmak genellikle kötü bir uygulamadır. Verilere erişmek için bir sınıfın iç yapısını kullanıyorsunuz. Mümkünse her zaman halka açık api'ye bağlı kalmaya çalışmalısınız. Özel üyelerin yansıması, tam bir güven ortamı gerektirir ve sınıfın içersinin zamanla değişebileceği için kırılgan kod olma potansiyeline sahiptir. –

6

System.Reflection ürününü denemelisiniz. İşte bir örnek:

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 
     } 
    } 
} 
+1

Sadece Silverlight kullanıyorsanız Özel üyelere erişemez. Olduğunu söylemedin, ama her ihtimale karşı. –

+0

Neden değil? Silverlight'ın dahili verilerine erişemediğinizi mi yoksa Silverlight'ın altındayken bunu yapamazsınız mı? –

+2

Silverlight ile çalışma zamanı, halka açık olmayan verilere bir güvenlik sorunu olarak yansıması aracılığıyla erişmenizi önler. Örneğin, bazı dosya I/O kodları çalışma zamanındadır, ancak normalde bunu yalnızca güvenlik endişelerini ihlal etmeyen özel yönetilen araçlarla erişebilirsiniz. Eğer gizli dosya G/Ç, nitty-cesur aşağı almak için yansıma kullanabiliyorsanız, o zaman sadece kötü amaçlı bir Silverlight sayfasına göz atarak bilgisayar dosyaları irade olabilir/okuyabilirsiniz. –

3

, daha kolay olabilir:

Düzenleme Siz de değerini ayarlamak mümkün gerek sayılabilir

, hala yansıma önleyebilirsiniz System.Guid.ToByteArray()'dan c almak için.

byte[] guid = guid.ToByteArray(); 
short c = (short)((guid[7] << 8) | guid[6]); 

Bu yaklaşım, genel ve belgelenmiş yöntemleri kullandığı için, sürümler arasında değişime daha az tabidir. (Genelde, özel uygulama ayrıntılarını güvenerek bu ayrıntılar sürüm sürüm değiştirebilirsiniz, çünkü kaçınılmalıdır.)

+0

Teşekkürler, ama değeri de ayarlayabilmem gerekiyor. – godzcheater

1

herhangi bir türdeki herhangi bir özel alanı almak için bir uzantısı yöntemi olabilir:

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); 
} 

ve sonra keyfi bir türde bir özel alan erişme:

Guid id = Guid.NewGuid(); 
Int16 c = id.GetFieldValue<Int16>("_c"); 
İlgili konular