Làm cách nào để lấy PropertyInfo của một thuộc tính cụ thể?


79

Tôi muốn lấy PropertyInfo cho một thuộc tính cụ thể. Tôi có thể dùng:

foreach(PropertyInfo p in typeof(MyObject).GetProperties())
{
    if ( p.Name == "MyProperty") { return p }
}

Nhưng phải có một cách để làm điều gì đó tương tự như

typeof(MyProperty) as PropertyInfo

Lanhung? Hay tôi bị mắc kẹt khi thực hiện so sánh chuỗi kiểu không an toàn?

Chúc mừng.

Câu trả lời:


59

Bạn có thể sử dụng nameof()toán tử mới là một phần của C # 6 và có sẵn trong Visual Studio 2015. Thông tin thêm tại đây .

Đối với ví dụ của bạn, bạn sẽ sử dụng:

PropertyInfo result = typeof(MyObject).GetProperty(nameof(MyObject.MyProperty));

Trình biên dịch sẽ chuyển đổi nameof(MyObject.MyProperty)thành chuỗi "MyProperty" nhưng bạn có được lợi ích là có thể cấu trúc lại tên thuộc tính mà không cần phải nhớ thay đổi chuỗi vì Visual Studio, ReSharper và những thứ tương tự biết cách cấu trúc lại nameof()giá trị của bộ cấu trúc .


1
Nếu có thể được cho là rõ ràng hơn một chút nếu ví dụ của bạn bắt đầu bằng PropertyInfo result =thay vì var result =.
DavidRR

133

Có một cách .NET 3.5 với lambdas / Expressionkhông sử dụng chuỗi ...

using System;
using System.Linq.Expressions;
using System.Reflection;

class Foo
{
    public string Bar { get; set; }
}
static class Program
{
    static void Main()
    {
        PropertyInfo prop = PropertyHelper<Foo>.GetProperty(x => x.Bar);
    }
}
public static class PropertyHelper<T>
{
    public static PropertyInfo GetProperty<TValue>(
        Expression<Func<T, TValue>> selector)
    {
        Expression body = selector;
        if (body is LambdaExpression)
        {
            body = ((LambdaExpression)body).Body;
        }
        switch (body.NodeType)
        {
            case ExpressionType.MemberAccess:
                return (PropertyInfo)((MemberExpression)body).Member;
            default:
                throw new InvalidOperationException();
        }
    }
}

Giải pháp tốt nhưng tiếc là tôi không sử dụng .NET3.5. Vẫn, đánh dấu!
tenpn

1
Trong 2.0, câu trả lời của Vojislav Stojkovic là câu trả lời gần nhất mà bạn có thể nhận được.
Marc Gravell

4
một câu hỏi: tại sao lại có một bài kiểm tra trên "body is LambdaExpression" trước khi nó trích xuất thuộc tính .Body? Không phải bộ chọn luôn luôn là một LambdaExpression?
tigrou

@tigrou hoàn toàn có thể chỉ là một sự giám sát và có lẽ tôi đang mượn mã hiện có hoạt động chống lạiExpression
Marc Gravell

@MarcGravell triển khai này không được tốt cho lắm. Bạn không nhận được thông tin tài sản chính xác trong trường hợp PropertyHelper<Derived>.GetProperty(x => x.BaseProperty);. Xem stackoverflow.com/questions/6658669/…
nawfal

12

Bạn có thể làm được việc này:

typeof(MyObject).GetProperty("MyProperty")

Tuy nhiên, vì C # không có kiểu "ký hiệu", nên không có gì có thể giúp bạn tránh sử dụng chuỗi. Nhân tiện, tại sao bạn lại gọi kiểu này là không an toàn?


38
Bởi vì nó không được đánh giá tại thời điểm biên dịch? Nếu tôi thay đổi tên thuộc tính của mình hoặc đánh máy chuỗi, tôi sẽ không biết cho đến khi mã chạy.
tenpn

1

Phản xạ được sử dụng để đánh giá kiểu thời gian chạy. Vì vậy, hằng số chuỗi của bạn không thể được xác minh tại thời điểm biên dịch.


5
Đó là những gì OP đang cố gắng tránh. Không chắc chắn nếu điều này trả lời câu hỏi.
nawfal 13/12/13

Điểm tốt liên quan đến thời gian biên dịch so với thời gian chạy và mục đích ban đầu của OP mặc dù tránh các chuỗi mã cứng dường như vẫn là giải pháp sạch nhất - tránh khả năng mắc lỗi chính tả, cho phép cấu trúc lại dễ dàng hơn và tạo phong cách mã sạch hơn.
Brian Sweeney
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.