【发布时间】:2016-01-04 14:20:36
【问题描述】:
我正在尝试创建一个简单的报告工具,用户可以在其中从一组 KPI、图表、聚合函数和其他参数中进行选择,单击一个按钮,然后调用 wcf 服务,然后返回自定义包含所有数据的模型。然后可以将其显示在 MVC/WPF 应用程序中(可能两者都有)。
由于用户可能来自多个国家/地区,我想使用数据注释以适合当前用户习惯的语言和数字格式的方式描绘所有数字和标题。
数据的加载和所有这些东西都工作得很好,没有任何问题。此外,我使用数据注释,因此所有语言/文化特定的设置都得到了照顾。当我尝试将所有数据放入要向用户显示的模型中时,问题就开始了。
我想要做的是有一个 Report 类,它包含一组列。每列可以是一个 int/double/... 值的列表。现在,由于我正在处理 WCF 并且上述解释暗示(据我所知)泛型的使用,我假设我可以将 [KnownType] 或 [ServiceKnownType] 用于类/wcf 操作,而实际使用基类型或接口作为返回值。从来没有真正尝试过,但我发现了一些对我来说似乎很合乎逻辑的很好的解释,所以我认为这部分不会有任何大问题(至少我希望不会)。
现在,我的界面是这样的(简化以关注我遇到的实际问题):
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; } }
由于每列中的值可能是 int/double/...,我假设我必须有一个仅用于该值的实际类(我认为我不能在集合类型上使用数据注释属性) ,因此:
public class IntValue: IValue<int>
{
[DisplayFormat(DataFormatString = "{0:#,##0;-#,##0;'---'}", ApplyFormatInEditMode = true)]
public int Value { get; set; }
}
当然,这看起来很奇怪,因为您可以将其设为实现 IValue 的通用类 Value 并完成它,但如果我做傻事并为每种可能的类型创建一个类(现在我键入它出来,这听起来很糟糕,我知道),我可以使用 DisplayFormat 属性,而不必担心它将自己呈现给用户的方式,它总是合适的。
现在,对于实现 IColumn 和 IReport 的类,这很简单:
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>>(); }
}
从接口和类列表中,您会立即看到,这使得在某些列具有其他类型的情况下无法生成报告。因此,不可能创建一个报告,其中一些列是 int,有些是 double,... 由于 IReport 中的通用约束让您指定一个类型,因此您对所有列都坚持这一点,因为它向下传播到每一列……这正是我真正想要的。
我觉得我无处可去,并且可能错过了一些非常简单的东西,因此我们将不胜感激。
TL;DR:如何获得非泛型类型的泛型集合?
【问题讨论】:
-
您不能将您的报告创建为
new IReport<IConvertible>吗? -
据我现在所见,这不允许我添加一个 int 或 double 列,因为它希望它们是 IConvertible,而不是任何 IConvertible 实现类。