C# ,但我认为基本框架就在那里。你不能将你的报告创建为新IReport?就我现在所见,这不允许我添加int或double列,因为它希望它们是IConvertible的,而不是任何IConvertible实现类。是的,是的,谢谢。我马上就去试试。我假设数据注释部

C# ,但我认为基本框架就在那里。你不能将你的报告创建为新IReport?就我现在所见,这不允许我添加int或double列,因为它希望它们是IConvertible的,而不是任何IConvertible实现类。是的,是的,谢谢。我马上就去试试。我假设数据注释部,c#,wcf,generics,C#,Wcf,Generics,,但我认为基本框架就在那里。你不能将你的报告创建为新IReport?就我现在所见,这不允许我添加int或double列,因为它希望它们是IConvertible的,而不是任何IConvertible实现类。是的,是的,谢谢。我马上就去试试。我假设数据注释部分随后将进入IValue的实际实现。但是,如果我确实想强制类的用户实际提供值类型,该怎么办?现在,它只是一组字符串,确实有效。但是,如果我想开始在计算中使用这些数据,该怎么办呢?…接下来我将介绍如何在数据上实现不同的聚合和计算。一旦这些值实现了


,但我认为基本框架就在那里。

你不能将你的报告创建为
新IReport
?就我现在所见,这不允许我添加int或double列,因为它希望它们是IConvertible的,而不是任何IConvertible实现类。是的,是的,谢谢。我马上就去试试。我假设数据注释部分随后将进入IValue的实际实现。但是,如果我确实想强制类的用户实际提供值类型,该怎么办?现在,它只是一组字符串,确实有效。但是,如果我想开始在计算中使用这些数据,该怎么办呢?…接下来我将介绍如何在数据上实现不同的聚合和计算。一旦这些值实现了一个已知的接口,访问者就可以随心所欲地处理接口调用的结果。e、 g.您有一个“DoubleSum”访问者,它会遍历IValues并尝试对其值求和。如果它不能强制任何值为double,它可以抛出,或者将该单元格视为零,或者您喜欢的任何东西。
public interface IReport<T> where T: IConvertible { ICollection<IColumn<T>> Columns { get; set; } }
public interface IColumn<T> where T: IConvertible { ICollection<IValue<T>> Values { get; set; } }
public interface IValue<T> where T: IConvertible { T Value { get; set; } }
public class IntValue: IValue<int>
{
    [DisplayFormat(DataFormatString = "{0:#,##0;-#,##0;'---'}", ApplyFormatInEditMode = true)]
    public int Value { get; set; }
}
public class Report<T>: IReport<T> where T: IConvertible 
{
    public ICollection<IColumn<T>> Columns { get; set; }
    public Report() { Columns=new List<IColumn<T>>(); }
}

public class Column<T>: IColumn<T> where T: IConvertible 
{
    public ICollection<IValue<T>> Values { get; set; }
    public Column() { Values = new List<IValue<T>>(); }
}
interface IReport
{
   IEnumerable<IColumn> Columns {get;}
}
interface IColumn
{
   IEnumerable IValue Values {get;}
}
interface IValue
{
   string AsString();
}
public interface IReport { ICollection<IColumn> Columns { get; set; } }
public interface IColumn { ICollection<Value> Values { get; set; } }

public interface IValue<T> where T: IConvertible { T Data { get; set; } }

public abstract class Value
{
    #region Formatting

    protected IFormatProvider Formatter { get; set; }
    protected abstract IFormatProvider GetFormatter();
    protected abstract string AsFormattedString();
    public override string ToString() { return AsFormattedString(); }

    #endregion

    public Value() { Formatter = GetFormatter(); }
}

public abstract class Value<T>: Value, IValue<T> where T: IConvertible
{
    #region IValue members

    public T Data { get; set; }

    #endregion

    #region Formatting

    protected override string AsFormattedString() { return Data.ToString(Formatter); }

    #endregion
}

public class IntValue: Value<int>
{
    public IntValue() { }
    public IntValue(string formatstring, int data) { Formatter = new IntFormatter(formatstring); Data = data; }

    #region Formatting

    protected override IFormatProvider GetFormatter() { return new IntFormatter(); }

    internal class IntFormatter: CustomFormatter
    {
        public IntFormatter() : this("{0:#,##0;-#,##0;'---'}") { }
        public IntFormatter(string formatstring) : base(formatstring) { }
    }

    #endregion
}

public class DoubleValue: Value<double>
{
    public DoubleValue() { }
    public DoubleValue(string formatstring, double data) { Formatter = new DoubleFormatter(formatstring); Data = data; }

    #region Formatting

    protected override IFormatProvider GetFormatter() { return new DoubleFormatter(); }

    internal class DoubleFormatter: CustomFormatter
    {
        public DoubleFormatter() : this("{0:0.#0;-0.#0;'---'}") { }
        public DoubleFormatter(string formatstring) : base(formatstring) { }
    }

    #endregion
}

public class ReportView: IReport
{
    public ICollection<IColumn> Columns { get; set; }
    public ReportView() { Columns = new List<IColumn>(); }
}

public class ReportColumn: IColumn
{
    public ICollection<Value> Values { get; set; }
    public ReportColumn() { Values = new List<Value>(); }
}
    // Creating a report
    IReport report = new ReportView();

    // Adding columns
    IColumn mycolumn = new ReportColumn();
    mycolumn.Values.Add(new IntValue() { Data = 1 });
    mycolumn.Values.Add(new DoubleValue() { Data = 2.7 });
    mycolumn.Values.Add(new IntValue("{0:#,##0;-#,##0;'---'}", 15));
    mycolumn.Values.Add(new DoubleValue("{0:0.#0;-0.#0;'---'}", 2.9));
    report.Columns.Add(mycolumn);

    // Looping through each column, and get each value in the formatted form
    foreach(var column in report.Columns)
    {
        foreach(var value in column.Values) { value.ToString(); }
    }