【问题标题】:c# hiding method on derived class and using Attributesc#在派生类上隐藏方法并使用属性
【发布时间】:2016-06-05 06:37:13
【问题描述】:

我有如下示例对象模型。

[AttributeUsage(AttributeTargets.Method)]
public sealed class CandidateApiForMenuItem : Attribute
{
    public CandidateApiForMenuItem(string caption)
    {
        this.Caption = caption;
    }

    public string Caption { get; set; }
}

public class FormDataElementBase
{
    public FormDataElementBase()
    {

    }

    [CandidateApiForMenuItem("Add PanelGroup")]
    public void AddPanelGroup()
    {
        ///...
    }

    [CandidateApiForMenuItem("Add BoxGroup")]
    public void AddBoxGroup()
    {
        ///...
    }


    [CandidateApiForMenuItem("Remove")]
    public void Remove()
    {
        ///...
    }

    public void GenerateGroupPopupMenuItems()
    {
        foreach (MethodInfo methodInfo in this.GetType().GetMethods())
        {
            if (methodInfo.GetCustomAttribute(typeof(CandidateApiForMenuItem)) != null)
            {
                // This is true both for FormDataElementBase and all derived
                // but I want to hide Remove method inside MainGroup class
                // However it is displayed again
            };
        };
    }
}

public class BoxGroup : FormDataElementBase
{

}

public class PanelGroup : FormDataElementBase
{

}

public class MainGroup : FormDataElementBase
{
    private void Remove()
    {
    }
}

当用户右键单击时,应用程序将显示 PopupMenu(GenerateGroupPopupMenuItems 方法)。菜单项将基于声明了 CandidateApiForMenuItem 的方法。但是,有些派生类 (MainGroup) 不应该显示某些方法 (f.e: Remove)。我所做的,在 MainGroup 内部将 Remove 方法声明为私有。但是,它会再次显示。

你能告诉我我在这里做什么吗?

谢谢。

【问题讨论】:

  • new public void Remove() => base.Remove(); 怎么样?
  • 这个条件也显示那个。 If(methodInfo.GetCustomAttribute(typeof(CandidateApiForMenuItem)) != null)...
  • 您没有“更改”删除为私有,您添加了另一个。查看警告窗口。
  • @Tim 如果在您的 GenerateGroupPopupMenuItems 方法中,您过滤的不仅仅是属性的存在怎么办?你在属性中给了自己一个 Caption 属性;如果您检查该属性以获取表示删除的特殊字符串值(定义为常量)怎么办?这避免了使用虚拟方法。

标签: c# reflection base derived custom-attribute


【解决方案1】:

首先,this.GetType().GetMethods() 不带参数只返回公共实例(即非静态)方法。所以MainGroup.Remove不会被这个调用返回。

如果您将MainGroup.Remove 设为公开,this.GetType().GetMethods() 将返回两种方法——基类和派生类。不是你想要的,我想。

如果您将FormDataElementBase.Remove 设为虚拟并MainGroup.Remove 覆盖,GetMethods 将仅返回一个Remove 方法(使用DeclaringType==typeof(MainGroup))- 这样会更好。

最后,我建议再引入一个属性,比如CandidateApiIgnore。如果我们用这个属性标记一个被覆盖的方法并以下面的方式修改GenerateGroupPopupMenuItems方法,这些东西应该可以工作:

[AttributeUsage(AttributeTargets.Method)]
public sealed class CandidateApiIgnore : Attribute
{
    public CandidateApiIgnore() { }
}

public class FormDataElementBase
{
///...
    [CandidateApiForMenuItem("Remove")]
    public virtual void Remove()
    {
        ///...
    }

    public void GenerateGroupPopupMenuItems()
    {
        foreach (MethodInfo methodInfo in this.GetType().GetMethods())
        {
            if (methodInfo.GetCustomAttribute(typeof(CandidateApiForMenuItem)) != null &&
                methodInfo.GetCustomAttribute(typeof(CandidateApiIgnore)) == null)
            {
                // If a method is overridden and marked with
                // CandidateApiIgnore attribute in a derived
                // class, it won't be processed here.
            };
        };
}

public class MainGroup : FormDataElementBase
{
    [CandidateApiIgnore]
    public override void Remove()
    {
        throw new NotSupportedException();
    }
}

【讨论】:

  • 添加一个新属性是个好主意,但是我正在寻找反射并且没有在基类上标记虚拟。谢谢。
猜你喜欢
  • 2010-11-27
  • 1970-01-01
  • 1970-01-01
  • 2010-11-23
  • 1970-01-01
  • 2013-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多