C# 通过在不进行类型检查的情况下对其父级进行操作来填充 ObjectB 字段

C# Populate ObjectB field by operating on its parent without type checking

对象 X 有一些对象 B 感兴趣的数据,但它在其父对象(对象 A)上运行。对象 B 声明了一个未在对象 A 中声明的字段。对象 C 也是对象 A 的子对象,但它没有声明对象 B 所声明的字段。

如何填充对象 B 字段? (类型检查和转换真的是唯一的解决方案吗?)

编辑(添加了示例)

public class ObjectX
{
    // eventually interested by ObjectB
    public float time;
    
    private ObjectA _objectAOrBStoredInAReference;

    public ObjectX(ObjectA objectAOrB)
    {
        this._objectAOrBStoredInAReference = objectAOrB;
    }

    public void PassTimeToObjectB()
    {
        // need to pass the time to ObjectB since it is interested in this
    }

    public void SomeStuffToDo()
    {
        PassTimeToObjectB();
        _objectAOrBStoredInAReference.StuffToDo();
    }

    public abstract class ObjectA
    {
        public abstract void StuffToDo();
    }
    
    public class ObjectB : ObjectA
    {
        public float time;

        public void SetTime(float time)
        {
            this.time = time;
        }

        public override void StuffToDo()
        {
            // Using Populated time here
        }
    }
}

我可以在这里看到几个解决方案:

1:只有ObjectX知道时间

如果time只有ObjectX可能知道,那么你可以将ObjectX作为参数传递给StuffToDo:

public class ObjectX
{
    // eventually interested by ObjectB
    private float time;

    // Expose 'time' as a readonly property - I'm assuming
    // other classes shouldn't need to manipulate it?
    public float Time => time;

    private ObjectA _objectAOrBStoredInAReference;

    public ObjectX(ObjectA objectAOrB)
    {
        this._objectAOrBStoredInAReference = objectAOrB;
    }

    public void SomeStuffToDo()
    {
        // Don't need to set the time anymore - 
        // ObjectB can retrieve the time itself.
        _objectAOrBStoredInAReference.StuffToDo(this);
    }
}

public class ObjectB : ObjectA
{
    // REMOVE ALL THIS CODE - NOT NEEDED ANYMORE
    //public float time;

    //public void SetTime(float time)
    //{
    //   this.time = time;
    //}

    public override void StuffToDo(ObjectX x)
    {
        var time = x.Time;
        // Do stuff involving 'time'.
    }
}

2:可以在整个解决方案范围内知道时间:

如果时间只是一般时间而不是特定于 ObjectX 然后通过它自己的类型公开它 ITimeProvider:

public interface ITimeProvider
{
    float Time { get;}
}

public class ObjectX
{
    // Remove any 'time' related stuff from X
    private ObjectA _objectAOrBStoredInAReference;

    public ObjectX(ObjectA objectAOrB)
    {
        this._objectAOrBStoredInAReference = objectAOrB;
    }

    public void SomeStuffToDo()
    {
        _objectAOrBStoredInAReference.StuffToDo();
    }
}

public class ObjectB : ObjectA
{
    private readonly ITimeProvider _timeProvider;
    public ObjectB(ITimeProvider timeProvider)
    {
        this._timeProvider = timeProvider;
    }
 
    public override void StuffToDo(ObjectX x)
    {
        var time = _timeProvider.Time;
        // Do stuff involving 'time'.
    }
}