代码之家  ›  专栏  ›  技术社区  ›  Robert Rossney

基类能否确定派生类是否重写了虚拟成员?

  •  6
  • Robert Rossney  · 技术社区  · 16 年前

    以下是我的课程的简化版本:

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

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

    因此,方法要做的(看起来)显而易见的事情是检查并查看当前实例的updateSharedData实现是否覆盖了基类的实现。我非常肯定,没有反射就不可能做到这一点,而且这可能是不可取的。

    我曾经想过一些解决办法,但它们都很尴尬:

    • 添加派生类的构造函数设置的受保护bool属性,并检查该属性以查看是否需要锁。这在隐藏派生类的锁定代码方面做得非常糟糕。
    • 使UpdateSharedData方法成为委托属性,具有任何派生类集 在其构造函数中获取私有方法的属性,并且仅在委托不为空时获取锁。那更好,但还是有点糟糕。
    3 回复  |  直到 8 年前
        1
  •  5
  •   tvanfosson    16 年前

    如果您定义了一个抽象任务和一个IHassharedData接口,那么在方法中,在执行锁之前,您将检查派生任务是否实现了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()
        {
           ...
        }
    }
    
        2
  •  4
  •   Chris Hynes    16 年前

    您只需稍加思考即可完成此项检查:

    bool IsUpdateSharedDataOverridden()
    {
        Type t = this.GetType();
        MethodInfo m = subType.GetMethod("UpdateSharedData");
    
        return m.DeclaringType == t && m.GetBaseDefinition().DeclaringType == typeof(Task);
    }
    
        3
  •  0
  •   LicenseQ    16 年前

    实际上,你说的是两个不同的对象:

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

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

    推荐文章