Cara mendapatkan properti Statis dengan Refleksi

109

Jadi ini tampaknya cukup mendasar tetapi saya tidak bisa membuatnya berfungsi. Saya memiliki sebuah Objek, dan saya menggunakan refleksi untuk mendapatkan properti publiknya. Salah satu properti ini statis dan saya tidak beruntung mendapatkannya.

Public Function GetProp(ByRef obj As Object, ByVal propName as String) as PropertyInfo
    Return obj.GetType.GetProperty(propName)

End Function

Kode di atas berfungsi dengan baik untuk properti Instans Publik, yang hingga saat ini adalah semua yang saya butuhkan. Seharusnya saya dapat menggunakan BindingFlags untuk meminta jenis properti lain (pribadi, statis), tetapi saya tidak dapat menemukan kombinasi yang tepat.

Public Function GetProp(ByRef obj As Object, ByVal propName as String) as PropertyInfo
    Return obj.GetType.GetProperty(propName, Reflection.BindingFlags.Static Or Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public)

End Function

Tapi tetap saja, meminta anggota Statis tidak menghasilkan apa-apa. Reflektor NET dapat melihat properti statis dengan baik, jadi jelas saya kehilangan sesuatu di sini.

Corey Downie
sumber
Ini sangat, sangat mirip dengan ini: stackoverflow.com/questions/392122/…
ctacke
Yah itu serupa karena mereka berdua menggunakan BindingFlags. Saya mencari kombinasi spesifik BindingFlag yang memungkinkan saya mendapatkan anggota Publik, baik itu Statis atau Instans.
Corey Downie

Jawaban:

129

Atau lihat saja ini ...

Type type = typeof(MyClass); // MyClass is static class with static properties
foreach (var p in type.GetProperties())
{
   var v = p.GetValue(null, null); // static classes cannot be instanced, so use null...
}
Ernest
sumber
2
Variabel mana yang sesuai dengan kedua null ini? Bagaimana Anda akan menulis ini menggunakan argumen bernama, jika memungkinkan? Terima kasih.
Hamish Grubijan
Untuk kelas statis internal?
Kiquenet
Ini adalah opsi terbaik, menurut saya harus dipilih sebagai jawabannya.
c0y0teX
8
p.GetValue(null);bekerja juga. Yang kedua nulltidak diperlukan.
Chrono
Tampak hebat. Tujuannya adalah mendapatkan properti berdasarkan argumen nama - saya rasa saya tidak ingin mengulang properti untuk mencapainya.
Corey Downie
42

Ini adalah C #, tetapi seharusnya memberi Anda ide:

public static void Main() {
    typeof(Program).GetProperty("GetMe", BindingFlags.NonPublic | BindingFlags.Static);
}

private static int GetMe {
    get { return 0; }
}

(Anda hanya perlu ATAU NonPublik dan Statis)

earlNameless
sumber
3
Dalam kasus saya, hanya menggunakan dua bendera ini tidak berhasil. Saya juga harus menggunakan bendera .FlattenHierarchy.
Corey Downie
3
@Corey setuju. BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchyadalah satu-satunya hal yang berhasil bagi saya.
Jonathon Reinhart
40

Sedikit kejelasan ...

// Get a PropertyInfo of specific property type(T).GetProperty(....)
PropertyInfo propertyInfo;
propertyInfo = typeof(TypeWithTheStaticProperty)
    .GetProperty("NameOfStaticProperty", BindingFlags.Public | BindingFlags.Static); 

// Use the PropertyInfo to retrieve the value from the type by not passing in an instance
object value = propertyInfo.GetValue(null, null);

// Cast the value to the desired type
ExpectedType typedValue = (ExpectedType) value;
George
sumber
1
BindingFlags.Instance | BindingFlags.Staticmemecahkannya untuk saya.
LosManos
28

Oke, jadi kuncinya bagi saya adalah menggunakan .FlattenHierarchy BindingFlag. Saya tidak begitu tahu mengapa saya menambahkannya pada sebuah firasat dan itu mulai bekerja. Jadi solusi terakhir yang memungkinkan saya mendapatkan Instans Publik atau Properti Statis adalah:

obj.GetType.GetProperty(propName, Reflection.BindingFlags.Public _
  Or Reflection.BindingFlags.Static Or Reflection.BindingFlags.Instance Or _
  Reflection.BindingFlags.FlattenHierarchy)
Corey Downie
sumber
7
myType.GetProperties(BindingFlags.Public | BindingFlags.Static |  BindingFlags.FlattenHierarchy);

Ini akan mengembalikan semua properti statis dalam kelas dasar statis atau tipe tertentu dan mungkin anak juga.

Igor
sumber
2

Hanya ingin mengklarifikasi ini untuk diri saya sendiri, saat menggunakan API refleksi baru berdasarkan TypeInfo- di mana BindingFlagstidak tersedia secara andal (tergantung pada kerangka kerja target).

Dalam refleksi 'baru', untuk mendapatkan properti statis untuk suatu tipe (tidak termasuk kelas dasar) Anda harus melakukan sesuatu seperti:

IEnumerable<PropertyInfo> props = 
  type.GetTypeInfo().DeclaredProperties.Where(p => 
    (p.GetMethod != null && p.GetMethod.IsStatic) ||
    (p.SetMethod != null && p.SetMethod.IsStatic));

Melayani baik untuk properti hanya baca atau hanya tulis (meskipun hanya tulis adalah ide yang buruk).

The DeclaredPropertiesanggota, juga tidak membedakan antara sifat dengan publik / accesor pribadi - sehingga untuk menyaring sekitar visibilitas, maka Anda perlu melakukannya berdasarkan accessor Anda perlu menggunakan. Misalnya - dengan asumsi panggilan di atas telah kembali, Anda dapat melakukan:

var publicStaticReadable = props.Where(p => p.GetMethod != null && p.GetMethod.IsPublic);

Ada beberapa metode pintasan yang tersedia - tetapi pada akhirnya kita semua akan menulis lebih banyak metode ekstensi di sekitar TypeInfometode / properti kueri di masa mendatang. Selain itu, API baru memaksa kita untuk memikirkan dengan tepat apa yang kita anggap sebagai properti 'pribadi' atau 'publik' mulai sekarang - karena kita harus menyaring diri kita sendiri berdasarkan pengakses individu.

Andras Zoltan
sumber
1

Di bawah ini sepertinya berhasil untuk saya.

using System;
using System.Reflection;

public class ReflectStatic
{
    private static int SomeNumber {get; set;}
    public static object SomeReference {get; set;}
    static ReflectStatic()
    {
        SomeReference = new object();
        Console.WriteLine(SomeReference.GetHashCode());
    }
}

public class Program
{
    public static void Main()
    {
        var rs = new ReflectStatic();
        var pi = rs.GetType().GetProperty("SomeReference",  BindingFlags.Static | BindingFlags.Public);
        if(pi == null) { Console.WriteLine("Null!"); Environment.Exit(0);}
        Console.WriteLine(pi.GetValue(rs, null).GetHashCode());


    }
}
Vyas Bharghava
sumber
-3

Coba link C # Reflection ini .

Perhatikan, menurut saya BindingFlags.Instance dan BindingFlags.Static bersifat eksklusif.

Ken Henderson
sumber
Ya saya berharap bukan itu masalahnya, karena yang saya inginkan saya bisa mendapatkan Instans Publik atau Statis.
Corey Downie
Mereka tidak eksklusif. Saya baru saja mengujinya.
LosManos