是否可以将委托作为属性参数?

Geo*_*lva 43 c# delegates custom-attributes

是否可以将委托作为属性的参数?

像这样:

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
{
}
Run Code Online (Sandbox Code Playgroud)

如果不可能,那么明智的选择是什么?

nem*_*esv 38

不,您不能将委托作为属性构造函数参数.查看可用类型:属性参数类型
作为一种解决方法(尽管它很容易出错并且容易出错)您可以使用反射创建一个委托:

[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(typeof(ConnectionPropertiesDelegate), delegateType, delegateName);
    }
}

[Workspace(typeof(TestDelegate), "GetConnection")]
public class Test
{
}
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,现在使用C#6可以改为:[Workspace(typeof(TestDelegate),nameof(TestDelegate.GetConnection))]这似乎可以解决由于重构而导致错误的问题. (16认同)
  • 实际上这是一个很好的解决方法.我为此做了一个特殊的界面,但委托更容易了.谢谢! (2认同)

dad*_*dhi 14

其他可能的解决方法是使用与委托定义匹配的抽象方法创建抽象基类属性类型,然后在具体的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
{
}
Run Code Online (Sandbox Code Playgroud)