我很难找到正确的方法:
我的数据结构:
public abstract class Flow
{
public virtual double Value { get; set; }
public virtual DateTime Time { get; set; }
}
public class InboundFlow : Flow
{
}
public class OutboundFlow : Flow
{
}
我的业务对象包含这些数据结构的集合
public abstract class Fluent
{
public virtual IList<Flow> FlowCollection { get; set; }
public virtual double InitialBaseflow { get; set; }
}
public class Affluent : Fluent
{
public new virtual IList<InboundFlow> FlowCollection { get; set; }
}
public class Effluent : Fluent
{
public new virtual IList<OutboundFlow> FlowCollection { get; set; }
}
我尝试使用的通用方法:
private static void FindInitialBaseflow<T>(ref T fluent) where T : Fluent
{
var linqFluent = fluent;
var flows = linqFluent.FlowCollection.ToList().FindAll(
flow =>
flow.Time >= SOME_DATE &&
flow.Time < SOME_OTHER_DATE);
var initialBaseflow = flows.Average(flow => flow.Value);
fluent.InitialBaseflow = Math.Round(initialBaseflow, 5);
}
我的问题是,在linq方法中调用"linqfluent.FlowCollection"会调用基类Fluent的FlowCollection,它为null。
我怎样才能强制使用孩子的财产?谢谢
您需要使Fluent
中的集合通用,以便从中继承的类可以指定类型:
public class Fluent<T>
where T : Flow
{
public IList<T> FlowCollection { get; set; }
public double InitialBaseflow { get; set; }
}
一旦你有了它,你甚至不需要Flow
的子类,你就可以把它具体化。
你对它的使用可以很容易地修改以适应这个模型:
private static void FindInitialBaseflow<T>(Fluent<T> fluent)
where T : Flow
{
var linqFluent = fluent;
var flows = linqFluent.FlowCollection.Where(
flow =>
flow.Time >= SOME_DATE &&
flow.Time < SOME_OTHER_DATE);
var initialBaseflow = flows.Average(flow => flow.Value);
fluent.InitialBaseflow = Math.Round(initialBaseflow, 5);
}
还要注意的是,由于在此方法中没有设置fluent
,因此不需要通过引用传递它。它已经是一个类,所以它本身就是一个引用;调用方将观察到引用对象的突变。
泛型是错误的工具。您应该使用多态性来确保根据类型调用正确的实现。
例如:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace ConsoleApp
{
public abstract class Flow
{
public virtual double Value { get { return new Random().Next() ; } }//these values are just for demonstration purposes
public virtual DateTime Time
{
get
{
return DateTime.MinValue.AddYears(1);
}
}
}
public class InboundFlow : Flow
{
}
public class OutboundFlow : Flow
{
}
public abstract class Fluent
{
IList<Flow> _flowCollection;
public virtual IList<Flow> FlowCollection
{
get { return _flowCollection; }
set { _flowCollection = value; }
}
private double _initialBaseflow;
public virtual double InitialBaseflow
{
get { return _initialBaseflow; }
set { _initialBaseflow = value; }
}
public Fluent()
{
FlowCollection = new List<Flow>();
}
}
public class Affluent : Fluent
{
//public new virtual IList<InboundFlow> FlowCollection { get; set; }//Keep the property polymorphic
public Affluent()
{
FlowCollection = new List<Flow>();
}
}
public class Effluent : Fluent
{
//public new virtual IList<OutboundFlow> FlowCollection { get; set; }
public Effluent()
{
FlowCollection = new List<Flow>();
}
}
class Program
{
public static DateTime SOME_DATE { get { return DateTime.MinValue; } }
public static DateTime SOME_OTHER_DATE { get { return DateTime.Now; } }
static void Main(string[] args)
{
var inbound = new InboundFlow();
var inbound2 = new InboundFlow();
var outbound = new OutboundFlow();
var a = new Affluent();
a.FlowCollection.Add(inbound);
a.FlowCollection.Add(inbound2);
FindInitialBaseflow(a);
}
private static void FindInitialBaseflow(Fluent fluent)
{
var linqFluent = fluent;
var flows = linqFluent.FlowCollection.ToList().FindAll(
flow =>
flow.Time >= SOME_DATE &&
flow.Time < SOME_OTHER_DATE);
var initialBaseflow = flows.Average(flow => flow.Value);
fluent.InitialBaseflow = Math.Round(initialBaseflow, 5);
}
}
}