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.


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...
}

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)


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;

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)

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.


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.


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


    }
}

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.