1

我很难找到正确的方法来解决这个问题:

我的数据结构:

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,它是空的。

我怎样才能强制使用孩子的财产呢?谢谢!

4

2 回答 2

1

您需要在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在此方法中进行设置,因此无需通过引用传递它。它已经是一个类,所以它本身就是一个引用;调用者将观察到引用对象的突变。

于 2013-08-13T15:26:13.967 回答
-1

泛型是错误的工具。您应该使用多态性来确保根据类型调用正确的实现。

例如:

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);
        }
    }
}
于 2013-08-13T15:30:12.100 回答