I am trying to create a simple reporting tool in which the user can select from a set of KPI parameters, diagrams, aggregate functions and other parameters, click a button, and then the wcf service is called, which then returns the user model with all the data. This can then be displayed in an MVC / WPF application (there may be both).
Since users can be from several countries, I want to use data annotations to portray all numbers and headers according to the language formats and the numbers that the current user is using.
Downloading data and all this stuff is working fine, no problem. In addition, I use data annotations, so all language / culture settings are taken into account. Problems arise when I try to put all the data in the model that I want to display to the user.
What I'm trying to do is report class containing a set of columns. Each column can be a list of int / double / values ββ.... Now, since I am dealing with WCF and the above explanation follows (as I understand it) the use of generics, I assume that I can use [KnownType] or [ServiceKnownType] for class / FOS operations, while actually using the base type or interface as the return value. I have never tried this, but I found some useful explanations that seem to me pretty logical, so I assume that I will not have any big problems for this part (at least I hope not).
Currently, my interfaces as such (simplified to focus on the actual problem that I have):
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; } }
Since the value in each column can be int / double / ..., I assume that I should have an actual class only for the value (I don't think I can use the data annotation attribute for the collection type) as such:
public class IntValue: IValue<int> { [DisplayFormat(DataFormatString = "{0:#,##0;-#,##0;'---'}", ApplyFormatInEditMode = true)] public int Value { get; set; } }
Of course, this looks strange, because you can just make it a common Value class that implements IValue and execute with it, but if I do a stupid thing and create a class for every possible type (now when I type it it sounds really bad, I I know), I can use the DisplayFormat attribute and do not have to worry about how it will be presented to the user, it will always be suitable.
Now for classes implementing IColumn and IReport, this is simple:
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>>(); } }
From the list of interfaces and classes, you will immediately see that this makes it impossible to have a report in which some columns have other types. Thus, it is impossible to create a report in which some columns are int, some of them double ... Since the general restriction in IReport forces you to specify the type, you are stuck with this for all columns, since it extends to the value of each column ... And this is exactly what i want really.
I feel like I'm not going anywhere, and I probably missed something really simple, so I could be pushed in the right direction.
TL DR: How to get a general collection in a non-generic type?