6

这是我的课程的简化版本:

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 的当前实例的实现是否覆盖了基类的实现。我很确定如果不使用反射,这是不可能的,而且这样做可能是不可取的。

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

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

3 回答 3

5

您可以通过一点反思来进行此检查:

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

    return m.DeclaringType == t && m.GetBaseDefinition().DeclaringType == typeof(Task);
}
于 2009-02-06T03:55:50.117 回答
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()
    {
       ...
    }
}
于 2009-02-06T03:59:49.267 回答
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();
    }
}

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

于 2009-02-06T04:12:53.920 回答