2009-10-18 27 views
7

Từ my recent question, tôi cố gắng tập trung mô hình miền bằng cách bao gồm một số logic ngớ ngẩn trong giao diện miền. Tuy nhiên, tôi đã tìm thấy một số vấn đề cần phải bao gồm hoặc loại trừ một số thuộc tính khỏi xác thực.Cách tốt nhất để xác định và truy cập các thuộc tính đã chọn trong C# là gì?

Về cơ bản, tôi có thể sử dụng cây biểu thức như mã sau đây. Tuy nhiên, tôi không thích nó vì tôi cần định nghĩa biến cục bộ ("u") mỗi khi tôi tạo biểu thức lambda. Bạn có bất kỳ mã nguồn nào ngắn hơn tôi không? Hơn nữa, tôi cần một số phương pháp để nhanh chóng truy cập các thuộc tính đã chọn.

public void IncludeProperties<T>(params Expression<Func<IUser,object>>[] selectedProperties) 
{ 
    // some logic to store parameter 
} 

IncludeProperties<IUser> 
(
    u => u.ID, 
    u => u.LogOnName, 
    u => u.HashedPassword 
); 

Cảm ơn,

Trả lời

9

Lambdas là tuyệt vời cho nhiều kịch bản - nhưng nếu bạn không muốn họ, có lẽ đơn giản là không sử dụng chúng? Tôi ghét phải nói nó, nhưng các chuỗi đơn giản được thử và thử nghiệm, đặc biệt là cho các tình huống như ràng buộc dữ liệu. Nếu bạn muốn truy cập nhanh, bạn có thể xem HyperDescriptor hoặc có cách biên dịch đại biểu cho người truy cập thuộc tính hoặc bạn có thể tạo Expression từ chuỗi và biên dịch nó (bao gồm dàn diễn viên thành object nếu bạn muốn chữ ký đã biết, thay vì gọi (chậm hơn nhiều) DynamicInvoke).

Tất nhiên, trong hầu hết các trường hợp, ngay cả phản xạ thô cũng đủ nhanh và không phải là nút cổ chai.

Tôi khuyên bạn nên bắt đầu bằng mã đơn giản nhất và kiểm tra xem đó có phải là thực sự quá chậm trước khi lo lắng về việc nó nhanh hay không. Nếu nó không phải là quá chậm, không thay đổi nó. Bất kỳ tùy chọn nào ở trên sẽ hoạt động theo cách khác.


Một suy nghĩ khác; nếu bạn đang sử dụng Expression, bạn có thể làm điều gì đó như:

public void IncludeProperties<T>(
    Expression<Func<T,object>> selectedProperties) 
{ 
    // some logic to store parameter 
} 

IncludeProperties<IUser>(u => new { u.ID, u.LogOnName, u.HashedPassword }); 

và sau đó tách biệt biểu thức? ngăn nắp Một chút, ít nhất ... đây là một số mẫu mã cho thấy sự giải cấu trúc:

public static void IncludeProperties<T>(
    Expression<Func<T, object>> selectedProperties) 
{ 
    NewExpression ne = selectedProperties.Body as NewExpression; 
    if (ne == null) throw new InvalidOperationException(
      "Object constructor expected"); 

    foreach (Expression arg in ne.Arguments) 
    { 
     MemberExpression me = arg as MemberExpression; 
     if (me == null || me.Expression != selectedProperties.Parameters[0]) 
      throw new InvalidOperationException(
       "Object constructor argument should be a direct member"); 
     Console.WriteLine("Accessing: " + me.Member.Name); 
    } 
} 
static void Main() 
{ 
    IncludeProperties<IUser>(u => new { u.ID, u.LogOnName, u.HashedPassword }); 
} 

Một khi bạn biết MemberInfo s (me.Member ở trên), xây dựng lambdas riêng bạn để truy cập cá nhân nên tầm thường. Ví dụ (bao gồm cả một dàn diễn viên để object để có được một chữ ký duy nhất):

var param = Expression.Parameter(typeof(T), "x"); 
var memberAccess = Expression.MakeMemberAccess(param, me.Member); 
var body = Expression.Convert(memberAccess, typeof(object)); 
var lambda = Expression.Lambda<Func<T, object>>(body, param); 
var func = lambda.Compile(); 
+0

oooh, đẹp một :) –

+0

gì là cách tốt nhất để giữ các thuộc tính được chọn để truy cập nhanh? Danh sách ? –

+0

'MemberInfo' sẽ ổn; 'Func ' (hoặc 'Func ') sẽ là tốt; một 'PropertyDescriptor' sẽ là tốt (đặc biệt là với HyperDescriptor). Nó sẽ hoạt động theo cách ... –

1

Dưới đây là các biểu hiện ngắn nhất tôi có thể đưa ra:

public static void IncludeProperties(Expression<Action<IUser>> selectedProperties) 
{ 
    // some logic to store parameter 
} 

public static void S(params object[] props) 
{ 
    // dummy method to get to the params syntax 
} 

[Test] 
public void ParamsTest() 
{ 
    IncludeProperties(u => S(
     u.Id, 
     u.Name 
     )); 

} 
+0

Nếu bạn sử dụng một kiểu ẩn danh và trình khởi tạo (xem câu trả lời đã cập nhật của tôi), bạn không cần phương thức giả. Đó là tốt đẹp –

+0

Vâng, tôi thấy rằng bây giờ :) –

Các vấn đề liên quan