2011-10-09 91 views
35

是否可以將委託作爲參數的參數?是否有可能擁有一個委託作爲屬性參數?

像這樣:

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 
{ 
} 

如果它不是可能的,什麼是明智的選擇嗎?

回答

29

不,您不能將委託作爲屬性構造函數參數。查看可用的類型:Attribute parameter types
作爲一種變通方法(雖然它的哈克,而且容易出錯),你可以創建一個delegate with reflection:用抽象方法

[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

其實這是一個很好的解決方法。我爲此構建了一個speficic接口,但代理非常簡單。謝謝! –

+0

這是一個解決方法,但不是一個好的方法。正如@nemesv所說的 - hacky和容易出錯的方式,因爲如果使用重構菜單將方法GetConnection的名稱更改爲其他名稱,字符串「GetConnection」將不會自動更改。 – prostynick

+0

那麼是否有可能在C#手動限制參數類型的構造函數?我沒有聽到有關它的信息,但正如我們在'Attribute'中看到的那樣,它是可能的。怎麼樣? – monstr

9

其他可能的解決方法是創建抽象基本屬性類型的匹配您的委託定義,然後在具體的Attribute類中實現該方法。

它具有以下優點:

  • 註釋更加簡潔和乾淨(DSL等)
  • 沒有反射
  • 易於重用

例子:

[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

我通過使用解決了這個問題一個枚舉和一個代表映射數組。雖然我非常喜歡使用繼承的想法,但在我的場景中,我需要編寫幾個子類才能完成相對簡單的工作。這也應該是可重構的。唯一的缺點是你必須確保數組中的委託索引對應於枚舉值。

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); 
} 
相關問題