I have rigged up a technique to handle multiple subreports in an rdlc report, but as I have tried to make it generic and repeatable, I have instead had to take the model and tweak it slightly for each case.
For example, if I define an abstract interface, like such, I just cut and paste it from winform to winform as needed:
abstract class ISolutionStrategy
{
public abstract void AlgorithmInterface(Int64 searchCriteria, SubreportProcessingEventArgs e);
}
First, I want to be able to bring this into each form by including an has-a object. I also want to encapsulate the behaviors of handling the dispatching by the delegate, and make the handling methods "generic" as well.
So, the design requirements are:
- Create an object that can be included in a winform to handle multiple subreport processing
- Instantiate and configure the object in the winform
- Build the dispatch table or switch/case statement in the winform
- Pass in all the methods to handle the specific requirments of that winform's report viewer
The GOAL is to make an object that can be tested standalone and made robust, and also to not have to cut and paste the wheel and do a bunch of manual tweaking for each new winform.
It seems to me that someone has found a better design out there than the one I currently have.
Create an object that can be included in a winform to handle multiple subreport processing
So far, I have a delegate in the local forms load event:
this.reportViewer1.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(LocalReport_SubreportProcessing);
which is handled by a switch statement in the *LocalReport_SubreportProcessing* method.
The body of the method contains a switch statement:
void LocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e)
{
String commonSubreportKey = _commonSubreportKey;
switch (e.ReportPath)
{
case "rptSubAlternateParts":
runSubAlternatePart(e, commonSubreportKey, new GetAlternateParts());
break;
case "rptSubGetAssemblies":
runSubFailurePart(e, commonSubreportKey, new GetAssemblies());
break;
case "rptSubGetAssemblies":
runSubGetGetEndItemLRMFailureInfo(e, commonSubreportKey, new GetEndItemLRMFailureInfo());
break;
case "rptSubGetAssemblies":
runSubGetSubAssemblies(e, commonSubreportKey, new GetSubAssemblies());
break;
default:
break;
}
Aside:In my opinion, the switch is mostly human readable compared to the alternative I considered. I considered using a hash with the report name as the key and the function call data as the value. However, I did not really know how to do it and I thought it would be harder for someone else to understand.
After that, a call is made to a function that rearranges the information passed from the function call in the switch statement:
private static void runSubAlternatePart(SubreportProcessingEventArgs e1, String commonReportKey, GetAlternatePart myAP)
{
myAP.AlgorithmInterface(commonReportKey, e1);
}
This rearrangement is definitely code stuttering, but is a seemingly necessary intermediate to the Strategy pattern I am attempting to implement:
abstract class IStrategy
{
public abstract void AlgorithmInterface(String searchParam, SubreportProcessingEventArgs e);
}
Here is a concrete implementation of the Strategy for one of the reports:
class GetAlternatePart : IStrategy
{
private BLL.AlternatePartBLL ds = new BLL.AlternatePartBLL();
public override void AlgorithmInterface(String searchParam, SubreportProcessingEventArgs e)
{
e.DataSources.Clear();
DataTable myDataTable = ds.GetAlternativePart(searchParam);
DataSet myDataSet = new DataSet();
myDataSet.Tables.Add(myDataTable);
e.DataSources.Add(new ReportDataSource("BLL_AlternatePartBLL", myDataSet.Tables[0]));
}
}
}
In any case, my desire is to not have to hand wire the same logic repeatedly between reports, as I have many reports with multiple subreports.
I would like a library quality way of using a class to dynamically create the middle parts where the stuttering occurs, and I would like to pass in an "anonymous" funciton which actually implements the detailed connecting of the subreport to its corresponding data source.
For a single report with subreports, or even a few one-off reports, what I am doing is ok, but how can it be made less manual, more robust and more testable?
My environment is Visual Studio 2008 with a target of .NET 3.5; there seems to be a difference in how abstract classes are declared and how they are compiled.