2011-10-09 69 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); 
} 
相关问题