基类可以确定派生类是否覆盖了虚拟成员吗?

Rob*_*ney 6 c# reflection inheritance overriding

这是我班级的简化版本:

public abstract class Task
{
    private static object LockObject = new object();

    protected virtual void UpdateSharedData() { }
    protected virtual void UpdateNonSharedData() { }

    public void Method()
    {
       lock(LockObject)
       {
          UpdateSharedData();
       }
       UpdateNonSharedData();
    }
}
Run Code Online (Sandbox Code Playgroud)

我试图隐藏派生类的锁定代码.但是如果派生类重写UpdateSharedData,我只想获取锁; 如果没有,我不希望该方法阻止并等待在更新共享数据之前更新共享数据的所有其他正在运行的实例.

所以对于Method来说(看似)显而易见的事情是检查并查看当前实例的UpdateSharedData实现是否覆盖了基类的实现.我很确定如果不使用反射这是不可能的,并且可能不希望这样做.

我已经想到了一些解决方法,但它们都很尴尬:

  • 添加派生类的构造函数设置的受保护bool属性,并检查该属性以查看是否需要锁定.这样做在隐藏派生类中的锁定代码方面做得非常糟糕.
  • 使UpdateSharedData方法成为委托属性,让任何派生类在其构造函数中将属性设置为私有方法,并且只有在委托不为空时才获取锁.那更好,但它仍然很糟糕.

Chr*_*nes 5

你可以用一点点反思来做这个检查:

bool IsUpdateSharedDataOverridden()
{
    Type t = this.GetType();
    MethodInfo m = subType.GetMethod("UpdateSharedData");

    return m.DeclaringType == t && m.GetBaseDefinition().DeclaringType == typeof(Task);
}
Run Code Online (Sandbox Code Playgroud)


tva*_*son 5

如果您定义了一个抽象Task和一个IHasSharedData接口,那么在Method中检查派生的Task是否在执行锁之前实现了IHasSharedData.只有实现接口的类才需要等待.我意识到这可以避免回答实际问题,但我认为这比使用反射更清晰.希望你能找到一个更好的界面名称,它更接近于类的实际功能.

public interface IHasSharedData
{
    void UpdateSharedData();
}

public abstract class Task
{
    private static object LockObject = new object();

    protected virtual void UpdateNonSharedData() { }

    public void Method()
    {
         if (this is IHasSharedData)
         {
            lock(LockObject)
            {
                UpdateSharedData();
            }
         }
         UpdateNonSharedData();
    }
}

public class SharedDataTask : Task, IHasSharedData
{
    public void UpdateSharedData()
    {
       ...
    }
}
Run Code Online (Sandbox Code Playgroud)