Ho implementato una tecnica per gestire più sottoreport in un rapporto rdlc, ma come ho cercato di renderlo generico e ripetibile, ho dovuto invece prendere il modello e modificarlo leggermente per ogni caso.Come può un delegato rispondere a più eventi con una classe generica ed estensibile?
Per esempio, se io definisco un'interfaccia astratta, come tale, ho appena tagliato e incollare da WinForm a WinForm in base alle esigenze:
abstract class ISolutionStrategy
{
public abstract void AlgorithmInterface(Int64 searchCriteria, SubreportProcessingEventArgs e);
}
In primo luogo, voglio essere in grado di portare questo in ogni forma includendo un oggetto has-a. Voglio anche incapsulare i comportamenti di gestione del dispacciamento da parte del delegato e rendere anche i metodi di gestione "generici".
Quindi, i requisiti di progettazione sono:
- creare un oggetto che può essere incluso in una WinForm di gestire più di elaborazione sottoreport
- un'istanza di e configurare l'oggetto nella winform
- Costruire la tabella di invio o switch/case statement nel winform
- Passa in tutti i metodi per gestire i requisiti specifici del visualizzatore di report di tale winform
L'obiettivo è di creare un oggetto che può essere testato autonomamente e reso robusto, e anche di non dover tagliare e incollare la ruota e fare un po 'di regolazione manuale per ogni nuova winform.
Mi sembra che qualcuno abbia trovato un design migliore rispetto a quello che ho attualmente.
Creare un oggetto che può essere inclusa in una WinForm per gestire l'elaborazione sottoreport multipla
Finora, ho un delegato in caso forme carico locale:
this.reportViewer1.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(LocalReport_SubreportProcessing);
che è gestito da un interruttore dichiarazione nel metodo * LocalReport_SubreportProcessing *.
Il corpo del metodo contiene un'istruzione switch:
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;
}
parte:A mio parere, l'interruttore è per lo più leggibile rispetto al alternativa ho considerato. Ho preso in considerazione l'utilizzo di un hash con il nome del report come chiave e la funzione chiama i dati come valore. Tuttavia, I non sapeva davvero come farlo e ho pensato che sarebbe stato più difficile da comprendere per lo .
Dopo di che, viene effettuata una chiamata a una funzione che riorganizza le informazioni passate dalla chiamata di funzione nella istruzione switch:
private static void runSubAlternatePart(SubreportProcessingEventArgs e1, String commonReportKey, GetAlternatePart myAP)
{
myAP.AlgorithmInterface(commonReportKey, e1);
}
Questa riorganizzazione è sicuramente codice di balbuzie, ma è un intermedio apparentemente necessario al modello di strategia che sto tentando di implementare:
abstract class IStrategy
{
public abstract void AlgorithmInterface(String searchParam, SubreportProcessingEventArgs e);
}
Ecco una concreta attuazione della strategia per uno dei report:
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 ogni caso, il mio desiderio è quello di non avere a filo mano la stessa logica più volte tra le relazioni, come ho molti rapporti con più sottoreport .
Vorrei un modo di libreria di utilizzare una classe per creare dinamicamente le parti centrali in cui si verifica la balbuzie, e vorrei passare in una funzione "anonima" che implementa effettivamente la connessione dettagliata del sottoreport alla sua corrispondente fonte di dati.
Per un singolo report con sottoreport, o anche alcuni report una tantum, quello che sto facendo va bene, ma come può essere reso meno manuale, più robusto e più testabile?
Il mio ambiente è Visual Studio 2008 con una destinazione .NET 3.5; sembra esserci una differenza nel modo in cui le classi astratte vengono dichiarate e in che modo vengono compilate.
Per ridurre al minimo il taglia e incolla, e per rimanere il più possibile ASCIUTATI, suggerirei un obiettivo di progettazione di avere meno codice in ogni Winform di quanto specificato. Ad esempio, hai bisogno di una tabella di spedizione in ogni WinForm, o potresti semplicemente nominare i tuoi metodi per abbinare e.ReportPath, e quindi richiamare tramite Reflection? Inoltre, il tuo codice di commutazione è illegale - hai 3 case "rptSubGetAssemblies", il che rende un po 'più difficile capire esattamente cosa stai cercando di fare. Potresti modificare per correggere il codice? –
Un altro pensiero che ho è che la necessità di una leggibilità umana impallidisce rispetto a rendere il codice ASCIUTTO. Se hai bisogno di utilizzare generici e alberi di espressioni nidificati qui per semplificare l'implementazione all'interno di ogni winform, allora questa è la cosa giusta da fare. –
Infine, quando si scrive "Passa in tutti i metodi per gestire i requisiti specifici del visualizzatore di report di questa finestra di esempio", quanto sono diversi questi metodi l'uno dall'altro? Derivano tutti della stessa classe base? Hanno firme di metodo simili tali da poter essere rappresentate da un delegato comune? Chiedo questo b/c non sono venduto per il bisogno di un modello di strategia qui, invece sospetto che questo potrebbe essere implementato più semplicemente con generici e riflessioni (se i tuoi metodi GetXxx sono molto simili tra loro), o alberi di espressione (in il caso più complesso che non sono). –