2011-10-09 25 views
35

Có thể có đại biểu làm tham số của thuộc tính không?Có thể có đại biểu làm tham số thuộc tính không?

Như thế này:

public delegate IPropertySet ConnectionPropertiesDelegate(); 

public static class TestDelegate 
{ 
    public static IPropertySet GetConnection() 
    { 
     return new PropertySetClass(); 
    } 
} 

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface,AllowMultiple=false,Inherited=true)] 
public class WorkspaceAttribute : Attribute 
{ 
    public ConnectionPropertiesDelegate ConnectionDelegate { get; set; } 

    public WorkspaceAttribute(ConnectionPropertiesDelegate connectionDelegate) 
    { 
     ConnectionDelegate = connectionDelegate; 
    } 
} 

[Workspace(TestDelegate.GetConnection)] 
public class Test 
{ 
} 

Và nếu nó không thể, lựa chọn thay thế hợp lý là gì?

Trả lời

29

Không, bạn không thể có đại biểu làm tham số hàm tạo thuộc tính. Xem các loại có sẵn: Attribute parameter types
Là một workaround (mặc dù nó hacky và dễ bị lỗi), bạn có thể tạo một delegate with reflection: trừu tượng loại cơ sở thuộc tính

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false, Inherited = true)] 
public class WorkspaceAttribute : Attribute 
{ 
    public ConnectionPropertiesDelegate ConnectionDelegate { get; set; } 

    public WorkspaceAttribute(Type delegateType, string delegateName) 
    { 
     ConnectionDelegate = (ConnectionPropertiesDelegate)Delegate.CreateDelegate(delegateType, delegateType.GetMethod(delegateName)); 
    } 
} 

[Workspace(typeof(TestDelegate), "GetConnection")] 
public class Test 
{ 
} 
+2

Thực ra đây là giải pháp tốt. Tôi đã xây dựng một giao diện speficic để làm điều này, nhưng các đại biểu là sooo dễ dàng hơn nhiều. Cảm ơn! –

+0

Đó là một giải pháp thay thế, nhưng không phải là giải pháp tốt. Nó chính xác như @nemesv nói - hacky và error dễ bị, bởi vì nếu bạn thay đổi tên của phương thức GetConnection thành cái gì đó khác bằng cách sử dụng trình đơn cấu trúc lại, chuỗi "GetConnection" sẽ không bị thay đổi tự động. – prostynick

+0

Vì vậy, có một khả năng trong C# thủ công hạn chế loại đối số của nhà xây dựng? Tôi không nghe thấy gì về nó, nhưng như chúng ta thấy trong kiểu 'thuộc tính', điều đó là có thể. Làm sao? – monstr

9

workaround thể khác được tạo ra bằng phương pháp trừu tượng kết hợp định nghĩa đại biểu của bạn, và sau đó triển khai phương thức trong lớp Attribute cụ thể.

Nó có lợi ích sau:

  • Chú ngắn gọn hơn và sạch (DSL loại tương tự)
  • Không phản ánh
  • Dễ dàng để tái sử dụng

Ví dụ:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple=false, Inherited=true)] 
public abstract class GetConnectionAttribute : Attribute 
{ 
    public abstract IPropertySet GetConnection(); 
} 

public class GetConnectionFromPropertySetAttribute : GetConnectionAttribute 
{ 
    public override IPropertySet GetConnection() 
    { 
     return new PropertySetClass(); 
    } 
} 

[GetConnectionFromPropertySet] 
public class Test 
{ 
} 
1

Tôi đã giải quyết vấn đề này bằng cách sử dụng một enum và một mảng ánh xạ của các đại biểu. Mặc dù tôi thực sự thích ý tưởng của việc sử dụng thừa kế, trong kịch bản của tôi mà sẽ yêu cầu tôi viết nhiều lớp con để làm những thứ tương đối đơn giản. Điều này cũng nên được tái cấu trúc. Hạn chế duy nhất là bạn phải đảm bảo làm cho chỉ mục của đại biểu trong mảng tương ứng với giá trị enum.

public delegate string FormatterFunc(string val); 

public enum Formatter 
{ 
    None, 
    PhoneNumberFormatter 
} 

public static readonly FormatterFunc[] FormatterMappings = { null, PhoneNumberFormatter }; 

public string SomeFunction(string zzz) 
{ 
    //The property in the attribute is named CustomFormatter 
    return FormatterMappings[(int)YourAttributeHere.CustomFormatter](zzz); 
} 
Các vấn đề liên quan