The reflection samples...are available at my blog...and are the same thing
Jon and Scott are speaking of.
....
My architecture for this scenario.
Reports
Same Baseline Data.
Different presentation needs per customer.
....................
Create STRONG datasets to represent mini portions of the data you need.
(This will become important as you pick which presentation layer you use)
Create a several strong datasets...for each need (not how it looks, but just
the data you need).
BillingByHealthPlanDS
BillingByCompanyDS
BillingByCustomerDS
You're doing this so you can get REUSE from these.
Write code to pull data (stored procedure?) and populate each of the DS's
above.
...........
THEN, lets say you have 2 customers..and each one wants to see the 3 sets of
data above in a different format.
(Let's pretend one likes white background, and one likes pink background)
IReport
--DisplayReport
--SetDataSource( DataSet ds );
IHealthPlanReport : IReport
--DisplayReport (comes from the previous interface)
IHealthPlanReport : IReport
--DisplayReport (comes from the previous interface)
ICompanyReport : IReport
--DisplayReport (comes from the previous interface)
ICustomerReport : IReport
--DisplayReport (comes from the previous interface)
The DisplayReport method will be the code which actually generates the
Excel (or whatever) you need.
You'll write 2 concretes for each of the 3 interfaces:
Company1HealthPlanReport : IHealthPlanReport
Company2HealthPlanReport : IHealthPlanReport
Company1CompanyReport : ICompanyReport
Company2CompanyReport : ICompanyReport
Company1CustomerReport : ICustomerReport
Company2CustomerReport : ICustomerReport
..........
I'm show one of the reports code:
public class Company1CustomerReport : ICustomerReport
{
private BillingByCustomerDS _modelDS = null;
public voic SetDataSource(DataSet ds)
{
this._modelDS = ds as BillingByCustomerDS;
if(null==this._modelDS)
{
throw new ArgumentNullException("DS was null, or the WRONG concrete type of
DataSet");
}
}
public void DisplayReport ()
{
//some how use _modelDS ...to create Excel AND give it a WHITE
backgroud, not pink
Console.WriteLine( _modelDS.GetXml());//<<the crappiest "Show Report"
method you'll ever see
}
}
Now you can use my blog article..and use reflection to load one of the
concretes...per Company.
I know it doesn't map perfectly like that...BUT you've got some ideas now.
By putting work into the strong dataset creation..you get reuse.
Then your code can be something like this:
BillingByCustomerDS ds = new BillingByCustomerDS(); // use something like
LoadDataSet to actually populate values)
IReport rpt1 = new Company1CustomerReport();
rpt1.SetDataSource(ds);
rpt1.DisplayReport();
And where I have
IReport rpt1 = new Company1CustomerReport();
you'll replace with some kind of reflection code (per my blog).
Or you might use the "By Key" method as well, and pass in the specific
customerID.
You need to work through my example blog code (downloadable) and actually
work with it some.
OO and interfaces aren't something you just "get" in one sitting.
Good luck.
You can also research the "Crystal Reports PUSH method" as well.
It will give you some clues as to why putting data into strong datasets..and
then PUSHING them into a report is a better plan of attack.
Even if you're NOT using Crystal Reports..it doesn't matter. The concepts
are good.
And if you ever decide to do something like
ActiveReports, Crystal Reports....then all that work you did with strong
datasets is reusable.
do NOT use the "pull" method.
..........
Outside of all that, you might consider Active Reports, since they have
pretty good licensing AND exporting features (to excel is one of them).
Now send my consulting free to my paypal account!! (
[email protected])
(ha ha)
If you don't know how to create a strong dataset or POPULATE a strong
dataset, check my blog entry "1.1 Custom Business Objects".
Ignore the customer business objects, and check the sample strong datasets,
tsql, and LoadDataSet methods I use.