2013-12-10 10 views
6

Tôi có một lớp đối tượng cơ sở dữ liệu mà làm một loạt các nâng nặng. Sau đó tôi mở rộng đối tượng đó và xây dựng các lớp đại diện cho các đối tượng thực tế và các trường đang được sửa đổi. Về cơ bản, nó trông giống như sau:C# Làm thế nào để có được tên của bất động sản được thiết lập

public class MyObject : DatabaseObject 
{ 
    public string FieldX 
    { 
     get { return GetValue<string>("FieldX"); } 
     set { SetValue<string>("FieldX", value); } 
    } 

    public int FieldY 
    { 
     get { return GetValue<int>("FieldY"); } 
     set { SetValue<int>("FieldY", value); } 
    } 
} 

public class DatabaseObject 
{ 
    public T GetValue<T>(string FieldName) 
    { 
     // Code that actually gets the right value 
    } 

    public void SetValue<T>(string FieldName, T value) 
    { 
     // Code that actually sets the value in the right place 
    } 
} 

Bằng cách này, sau này tôi có thể khởi tạo MyObject và bắt đầu thiết lập thuộc tính thông qua mã. Ý tưởng là tạo ra mã dễ bảo trì hơn, dễ bảo trì hơn.

Nó hoạt động tốt trong thực tế. Tuy nhiên, tôi nhận thấy rằng mã cho MyObject khá lặp đi lặp lại. Ví dụ, với FieldX, tôi sẽ chỉ định loại "chuỗi" bên trong get/set và cũng phải chỉ định tên thuộc tính "FieldX" trong get/set.

Tôi tự hỏi nếu có cách nào để đơn giản hóa mã hơn nữa để giảm sự lặp lại.

Tôi biết tôi có thể sử dụng Reflection:

MethodBase.GetCurrentMethod().Name.Substring(4) 

... bên trong get/set cuộc gọi để nhận các tên thuộc tính, và tôi có thể sử dụng GetType() để có được những loại giá trị khi thực hiện bộ, nhưng lý tưởng tôi muốn lấy tên thuộc tính ban đầu từ bên trong các phương thức GetValue/SetValue cơ bản (lý tưởng là không phân tích cú pháp dấu vết ngăn xếp).

Lý tưởng nhất, tôi đang tìm một cái gì đó như thế này:

public string FieldX 
    { 
     get { return GetValue(); } 
     set { SetValue(value); } 
    } 

    public int FieldY 
    { 
     get { return GetValue(); } 
     set { SetValue(value); } 
    } 

Bất kỳ suy nghĩ?

Trả lời

3

Thời lượng này dài hơn một chút so với bạn đang tìm kiếm, nhưng cũng có thể được sử dụng (sử dụng các biểu thức lambda mạnh mẽ được nhập lambda).

public class MyObject : DatabaseObject 
{ 
    public string FieldX 
    { 
     get { return GetValue(() => FieldX); } 
     set { SetValue(() => FieldX, value); } 
    } 

    public int FieldY 
    { 
     get { return GetValue(() => FieldY); } 
     set { SetValue(() => FieldY, value); } 
    } 
} 

public class DatabaseObject 
{ 
    public T GetValue<T>(Expression<Func<T>> field) 
    { 
     string fieldName = GetFieldName(field); 
     // Code that actually gets the right value 
    } 

    public void SetValue<T>(Expression<Func<T>> field, T value) 
    { 
     string fieldName = GetFieldName(field); 
     // Code that actually sets the value in the right place 
    } 

    private static string GetFieldName<T>(Expression<Func<T>> field) 
    { 
     return ((MemberExpression)field.Body).Member.Name; 
    } 
} 
7

C# 5.0 hỗ trợ điều này bằng cách sử dụng thuộc tính [CallerMemberName] trên tham số mặc định. Một cái gì đó như thế này:

public static object GetValue([CallerMemberName] string caller = "") 
{ 
    Trace.WriteLine("Called by: " + caller); 
    return null; 
} 

Và sẽ được sử dụng như:

public string FieldX 
{ 
    get { return (string)GetValue(); } 
} 

này hoạt động bằng trình biên dịch tự động cung cấp các tham số của GetValue dựa trên tên của người gọi.

Bạn có thể tìm hiểu thêm về tính năng này in MSDN.

Bạn có thể tạo GetValue chung để có thể sử dụng như GetValue<string>() trong thuộc tính của bạn.

+0

Tôi đoán tôi không thể đánh dấu cả hai câu trả lời là chính xác. Tôi nghĩ câu trả lời C# 5.0 ở trên có thể là cách tiếp cận dài hạn đúng, nhưng các yêu cầu của dự án không may giới hạn tôi sử dụng ngày hôm nay, vì vậy tôi phải quay lại câu trả lời dưới đây. – jhilgeman

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