【问题标题】:Placeholder of class that can be filled out later?可以稍后填写的班级占位符?
【发布时间】:2020-11-02 15:01:14
【问题描述】:

更新:我不再打算实现下面描述的逻辑,我完全使用了不同的实现。

假设我有一个集合,我使用 buffer 参数初始化该集合,该参数表示集合应始终包含的元素数量。在构建时,我想用占位符填充它,直到添加“真实”值或实例。添加实际值时,我希望最旧的占位符值更新其值以匹配“添加”值的值,而不是物理地将新数据添加到集合中。

为此,我想我可以写一个接口IPlaceholder,大致做这样的事情:

public interface IPlaceholder<T>
{
    public bool Placeholder { get; set; }
    public void UpdateValues(/* type specific constructor parameters? */);
    // public void UpdateValues(object[] params) is a last resort
}

例如,我可以对从传感器接收的数据使用缓冲区来跟踪传感器数据在过去 10 分钟内的变化情况:

public class SensorData : IPlaceholder<SensorData>
{
    public decimal? Sensor1 { get; set; } = null;
    public decimal? Sensor2 { get; set; } = null;
    public DateTime ReceiveTime { get; set; }
    public bool Placeholder { get; set; }

    public SensorData()
    {
        Placeholder = true;
        ReceiveTime = DateTime.Now;
    }
    public SensorData(DateTime t)
    {
        Placeholder = true;
        ReceiveTime = t;
    }
    public SensorData(decimal s1, decimal s2, DateTime t)
    {
        Sensor1 = s1;
        Sensor2 = s2;
        ReceiveTime = t;
        Placeholder = false;
    }
    
    // Use any of the possible constructor signatures as class?
    public void UpdateValues(decimal s1, decimal s2, DateTime t)
    {
        Sensor1 = s1;
        Sensor2 = s2;
        ReceiveTime = t;
        Placeholder = false;
    }
}

或者我可以在我知道他们必须完成的比赛中收集一组参赛者,因此缓冲区代表参赛者完成的顺序。

public class Racer : IPlaceholder<Racer>
{
    public string Name { get; set; } = null;
    public string RacerCar { get; set; } = null;
    public bool Placeholder { get; set; }

    public Racer()
    {
        Placeholder = true;
    }
    public Racer(string name, string racerCar)
    {
        Name = name;
        RacerCar = racerCar;
        PlaceHolder = false;
    }

    // Use any of the possible constructor signatures as class?
    public void UpdateValues(string name, string racerCar)
    {
        Name = name;
        RacerCar = racerCar;
    }
}

这个想法是,一旦实际数据开始流入,我可以给定一些占位符来初始化集合:

var racerCount = 6;
var racers = new CustomCollection<Racer>(racerCount); // Initializes 6 placeholder Racer objects

// Actual racers:
var john = new Racer("John Lennon", "Lucy");
var paul = new Racer("Paul McCartney", "Michelle");
var ringo = new Racer("Ringo Starr", "Octopus");
var george = new Racer("George Harrison", "Blue Jay");
var brian = new Racer("Brian Epstein", "Seltaeb");
var yoko = new Racer("Yoko Ono", "Samantha");

racers.Add(john);
/* John Finishes first 
=> calls racers.Where(x => x.Placeholder).First()
.UpdateValues(john.Name, john.RacerCar)
or something
*/
etc.

对于传感器示例,我可能还会添加向其中添加新数据的功能,在这种情况下,最旧的数据会被删除,所有现有数据都会被移回最新的传感器数据。

有没有办法实现一个接口来适应特定类型的构造参数来更新一个通用的占位符?

【问题讨论】:

  • 您能解释一下为什么要用占位符填充集合吗?我假设您在对数据进行任何类型的聚合时不会使用占位符值。在您的示例中,听起来像常规队列或环形缓冲区就足够了。
  • 我正在尝试绘制传感器数据,我希望该图显示 10 分钟的恒定范围。为了确保正确显示所有待处理数据,我打算用占位符填充我的集合,以便绘图将它们识别为现有(尽管是空的)数据。

标签: c# generics .net-core reflection interface


【解决方案1】:

您可以执行以下操作:

public interface IUpdateRequest<T> {
    T Update(IPlaceholder<T> t);
}

public interface IPlaceholder<T>
{
    public bool Placeholder { get; set; }
    public T UpdateValues(IUpdateRequest<T> updateRequest);
}

public abstract class PlacheholderBase<T>
{
    public virtual bool Placeholder {get;set;}
    public T UpdateValues(IUpdateRequest<T> updateRequest) => updateRequest.Update(this);
 
}

public class SensorData : PlaceholderBase<SensorData>
{
    public decimal? Sensor1 { get; set; } = null;
    public decimal? Sensor2 { get; set; } = null;
    public DateTime ReceiveTime { get; set; }

    public SensorData()
    {
        Placeholder = true;
        ReceiveTime = DateTime.Now;
    }
    public SensorData(DateTime t)
    {
        Placeholder = true;
        ReceiveTime = t;
    }
    public SensorData(decimal s1, decimal s2, DateTime t)
    {
        Sensor1 = s1;
        Sensor2 = s2;
        ReceiveTime = t;
        Placeholder = false;
    }
    
}

public class SensorDataUpdateRequest : IUpdateRequest<SensorData>
{
     public decimal Sensor1 {get;set;}
     public decimal Sensor2 {get;set;}
     public DateTime ReceiveTime {get;set;}

     public SensorData Update(SensorData s) {
        s.Sensor1 = this.Sensor1;
        s.Sensor2 = this.Sensor2;
        s.ReceiveTime = this.ReceiveTime;
        s.Placeholder = false;
     }
}

【讨论】:

  • 我需要接口和抽象类吗?
  • 抽象类是为了一次性实现UpdateValues
  • UpdateValues 应该在 SensorData 类中定义
  • 您能解释一下原因吗?
  • 我只是将您的代码复制并粘贴到一个单独的命名空间中,除了无效的返回类型(我将所有 Update 更改为 voids)之外,SensorDataUpdateRequest 类中仍然存在问题,即Update(SensorData s) 没有被识别为IUpdateRequest&lt;SensorData&gt;.Update(IPlaceholder&lt;SensorData&gt; t) 的正确签名。
猜你喜欢
  • 1970-01-01
  • 2020-09-09
  • 1970-01-01
  • 2011-06-22
  • 2016-10-29
  • 1970-01-01
  • 2022-12-11
  • 2011-07-11
  • 2011-03-19
相关资源
最近更新 更多