Cách lấy thuộc tính Tĩnh với Phản chiếu


109

Vì vậy, điều này có vẻ khá cơ bản nhưng tôi không thể làm cho nó hoạt động. Tôi có một Đối tượng và tôi đang sử dụng sự phản chiếu để truy cập các thuộc tính công khai của nó. Một trong những thuộc tính này là tĩnh và tôi không gặp may mắn khi sử dụng nó.

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

End Function

Đoạn mã trên hoạt động tốt cho các thuộc tính Public Instance, cho đến bây giờ là tất cả những gì tôi cần. Được cho là tôi có thể sử dụng BindingFlags để yêu cầu các loại thuộc tính khác (riêng tư, tĩnh), nhưng dường như tôi không thể tìm thấy sự kết hợp phù hợp.

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

Tuy nhiên, yêu cầu bất kỳ thành viên Static nào không trả lại gì. .NET phản xạ có thể nhìn thấy các thuộc tính tĩnh tốt, vì vậy rõ ràng tôi đang thiếu một cái gì đó ở đây.


Đây thực sự là, thực sự tương tự như sau: stackoverflow.com/questions/392122/...
ctacke

Nó giống nhau ở chỗ cả hai đều sử dụng BindingFlags. Tôi đang tìm kiếm một sự kết hợp cụ thể của BindingFlags sẽ cho phép tôi có được các thành viên Công khai, có thể là Tĩnh hoặc Phiên bản.
Corey Downie

Câu trả lời:


129

Hay chỉ cần nhìn vào cái này ...

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
Hai giá trị null này tương ứng với những biến nào? Làm thế nào bạn sẽ viết điều này bằng cách sử dụng các đối số được đặt tên, nếu nó có thể? Cảm ơn.
Hamish Grubijan

Đối với lớp tĩnh nội bộ?
Kiquenet

Đây là phương án tốt nhất, theo tôi nó nên được chọn làm câu trả lời.
c0y0teX

8
p.GetValue(null);hoạt động quá. Thứ hai nulllà không bắt buộc.
Chrono

Trông thật tuyệt. Mục đích là lấy thuộc tính dựa trên đối số tên - tôi không nghĩ mình muốn lặp lại thuộc tính để đạt được điều đó.
Corey Downie

42

Đây là C #, nhưng sẽ cung cấp cho bạn ý tưởng:

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

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

(bạn chỉ cần HOẶC NonPublic và Static)


3
Trong trường hợp của tôi, chỉ sử dụng hai cờ này không hoạt động. Tôi cũng phải sử dụng cờ .FlattenHierarchy.
Corey Downie

3
@CoreyDownie đã đồng ý. BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchylà điều duy nhất làm việc cho tôi.
Jonathon Reinhart

40

Rõ ràng một chút ...

// 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đã giải quyết nó cho tôi.
LosManos

28

Được rồi, vì vậy chìa khóa cho tôi là sử dụng .FlattenHierarchy BindingFlag. Tôi thực sự không biết tại sao tôi chỉ thêm nó vào một linh cảm và nó bắt đầu hoạt động. Vì vậy, giải pháp cuối cùng cho phép tôi có được Phiên bản Công khai hoặc Thuộc tính Tĩnh là:

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

Điều này sẽ trả về tất cả các thuộc tính tĩnh trong lớp cơ sở tĩnh hoặc một kiểu cụ thể và có thể là con nữa.


2

Tôi chỉ muốn làm rõ điều này cho bản thân tôi, trong khi sử dụng API phản chiếu mới dựa trên TypeInfo- nơi BindingFlagskhông có sẵn một cách đáng tin cậy (tùy thuộc vào khung mục tiêu).

Trong phản chiếu 'mới', để có được các thuộc tính tĩnh cho một kiểu (không bao gồm (các) lớp cơ sở), bạn phải thực hiện một số việc như:

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

Phục vụ cho cả thuộc tính chỉ đọc hoặc chỉ ghi (mặc dù chỉ ghi là một ý tưởng khủng khiếp).

Thành DeclaredPropertiesviên cũng không phân biệt các thuộc tính với người truy cập công khai / riêng tư - vì vậy để lọc xung quanh khả năng hiển thị, bạn cần thực hiện việc đó dựa trên trình truy cập mà bạn cần sử dụng. Ví dụ - giả sử cuộc gọi ở trên đã trở lại, bạn có thể làm:

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

Có một số phương thức phím tắt có sẵn - nhưng cuối cùng tất cả chúng ta sẽ viết nhiều phương thức mở rộng hơn xung quanh các TypeInfophương thức / thuộc tính truy vấn trong tương lai. Ngoài ra, API mới buộc chúng ta phải suy nghĩ về chính xác những gì chúng ta nghĩ là thuộc tính 'riêng tư' hoặc 'công khai' từ bây giờ - bởi vì chúng ta phải tự lọc dựa trên từng người truy cập.


1

Dưới đây dường như làm việc cho tôi.

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


    }
}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.