วิธีรับคุณสมบัติคงที่ด้วยการสะท้อนกลับ


109

ดูเหมือนจะค่อนข้างธรรมดา แต่ฉันไม่สามารถใช้งานได้ ฉันมีวัตถุและฉันใช้การสะท้อนเพื่อไปยังสมบัติสาธารณะ หนึ่งในคุณสมบัติเหล่านี้เป็นแบบคงที่และฉันไม่มีโชคที่จะได้รับมัน

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

End Function

โค้ดด้านบนใช้งานได้ดีสำหรับคุณสมบัติอินสแตนซ์สาธารณะซึ่งจนถึงตอนนี้คือทั้งหมดที่ฉันต้องการ สมมติว่าฉันสามารถใช้ BindingFlags เพื่อขอคุณสมบัติประเภทอื่น ๆ ได้ (ส่วนตัวแบบคงที่) แต่ดูเหมือนจะไม่พบชุดค่าผสมที่เหมาะสม

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

แต่ถึงกระนั้นการร้องขอให้สมาชิก Static ใด ๆ กลับไม่มีอะไรเลย ตัวสะท้อนแสง. NET สามารถดูคุณสมบัติคงที่ได้ดีดังนั้นฉันจึงพลาดบางอย่างที่นี่อย่างชัดเจน


นี่มันคล้าย ๆ กันจริงๆ: stackoverflow.com/questions/392122/…
ctacke

มันคล้ายกันตรงที่ทั้งคู่ใช้ BindingFlags ฉันกำลังมองหาชุดค่าผสมเฉพาะของ BindingFlags ที่จะช่วยให้ฉันได้รับสมาชิกสาธารณะไม่ว่าจะเป็นแบบคงที่หรืออินสแตนซ์
Corey Downie

คำตอบ:


129

หรือดูแค่นี้ ...

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
ค่าว่างทั้งสองนี้สอดคล้องกับตัวแปรใด คุณจะเขียนสิ่งนี้โดยใช้อาร์กิวเมนต์ที่ตั้งชื่อได้อย่างไรถ้าเป็นไปได้? ขอบคุณ.
Hamish Grubijan

สำหรับคลาสคงที่ภายใน?
Kiquenet

นี่เป็นตัวเลือกที่ดีที่สุดในความคิดของฉันควรเลือกเป็นคำตอบ
c0y0teX

8
p.GetValue(null);ได้ผลเช่นกัน ข้อที่สองnullไม่จำเป็นต้องใช้
Chrono

ดูดี. เป้าหมายคือการได้รับคุณสมบัติตามอาร์กิวเมนต์ชื่อ - ฉันไม่คิดว่าฉันต้องการที่จะวนซ้ำคุณสมบัติที่เคยมีมาเพื่อให้บรรลุเป้าหมายนั้น
Corey Downie

42

นี่คือ C # แต่ควรให้แนวคิด:

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

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

(คุณต้องหรือ NonPublic และ Static เท่านั้น)


3
ในกรณีของฉันการใช้เพียงสองแฟล็กนี้ไม่ได้ผล ฉันต้องใช้แฟล็ก. FlatHierarchy ด้วย
Corey Downie

3
@CoreyDownie เห็นด้วย BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchyเป็นสิ่งเดียวที่เหมาะกับฉัน
Jonathon Reinhart

40

ความกระจ่างเล็กน้อย ...

// 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.Staticแก้ไขให้ฉัน
LosManos

28

โอเคกุญแจสำคัญสำหรับฉันคือใช้. FlatHierarchy BindingFlag ฉันไม่รู้จริงๆว่าทำไมฉันถึงเพิ่มมันลงในลางสังหรณ์และมันเริ่มทำงาน ดังนั้นทางออกสุดท้ายที่ทำให้ฉันได้รับอินสแตนซ์สาธารณะหรือคุณสมบัติคงที่คือ:

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

สิ่งนี้จะส่งคืนคุณสมบัติคงที่ทั้งหมดในคลาสฐานแบบคงที่หรือประเภทเฉพาะและอาจเป็นลูกด้วย


2

แค่อยากจะชี้แจงสิ่งนี้สำหรับตัวเองในขณะที่ใช้ API การสะท้อนใหม่ตามTypeInfo- ซึ่งBindingFlagsไม่สามารถใช้ได้อย่างน่าเชื่อถือ (ขึ้นอยู่กับกรอบเป้าหมาย)

ในการสะท้อน 'ใหม่' เพื่อให้ได้คุณสมบัติคงที่สำหรับประเภท (ไม่รวมคลาสฐาน (es)) คุณต้องทำสิ่งต่างๆเช่น:

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

ให้บริการทั้งคุณสมบัติอ่านอย่างเดียวหรือเขียนอย่างเดียว (แม้ว่าการเขียนอย่างเดียวจะเป็นความคิดที่แย่มากก็ตาม)

DeclaredPropertiesสมาชิกมากเกินไปไม่แยกแยะระหว่างคุณสมบัติกับ accessors รัฐ / ภาคเอกชน - เพื่อที่จะกรองรอบมองเห็นแล้วคุณต้องทำมันขึ้นอยู่กับการเข้าถึงที่คุณจำเป็นต้องใช้ เช่น - สมมติว่ามีการโทรกลับด้านบนคุณสามารถทำได้:

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

มีวิธีทางลัดบางวิธีที่ใช้ได้ - แต่ท้ายที่สุดเราทุกคนจะต้องเขียนวิธีการขยายเพิ่มเติมเกี่ยวกับTypeInfoวิธีการสืบค้น / คุณสมบัติในอนาคต นอกจากนี้ API ใหม่ยังบังคับให้เราคิดถึงสิ่งที่เราคิดว่าเป็นทรัพย์สิน "ส่วนตัว" หรือ "สาธารณะ" นับจากนี้ไปเพราะเราต้องกรองตัวเองตามผู้เข้าถึงแต่ละคน


1

ด้านล่างดูเหมือนจะใช้ได้สำหรับฉัน

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


    }
}

-3

ลองใช้C # Reflection นี้ลิงค์นี้

หมายเหตุฉันคิดว่าBindingFlags.Instance และ BindingFlags.Staticเป็นเอกสิทธิ์


ใช่ฉันหวังว่าจะไม่เป็นเช่นนั้นเพราะสิ่งที่ฉันต้องการให้ฉันได้รับอินสแตนซ์สาธารณะหรือแบบคงที่
Corey Downie

พวกเขาไม่ได้เป็นเอกสิทธิ์ ฉันเพิ่งทดสอบมัน
LosManos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.