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

时间:2009-02-06 03:40:04

标签: c# reflection inheritance override

这是我班级的简化版本:

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();
    }
}

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

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

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

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

3 个答案:

答案 0 :(得分: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()
    {
       ...
    }
}

答案 1 :(得分:4)

你可以用反射的微笑来检查:

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

    return m.DeclaringType == t && m.GetBaseDefinition().DeclaringType == typeof(Task);
}

答案 2 :(得分:0)

实际上,你在谈论两个不同的对象:

public abstract class Task {    
    protected virtual void UpdateNonSharedData() { }

    public virtual void Method()    
    {   
        UpdateNonSharedData();    
    }
}

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

    protected virtual void UpdateSharedData() { }

    public overrides void Method()    
    {       
        lock(LockObject)
        {          
            UpdateSharedData();       
        }   
        base.Method();
    }
}

但是,更理想的解决方案将是战略模式。