W jaki sposób delegat może odpowiedzieć na wiele zdarzeń klasą ogólną i rozszerzalną?
Skonstruowałem technikę obsługi wielu podraportów w raporcie rdlc, ale ponieważ próbowałem uczynić go generycznym i powtarzalnym, musiałem wziąć model i nieco go ulepszyć dla każdego przypadku.
Na przykład, jeśli zdefiniuję abstrakcyjny interfejs, taki jak ten, po prostu wycinam i wklejam go z winform do winform w razie potrzeby:
abstract class ISolutionStrategy
{
public abstract void AlgorithmInterface(Int64 searchCriteria, SubreportProcessingEventArgs e);
}
Po pierwsze, chcę być w stanie wprowadzić to do każdego formularza, włączając obiekt ma-a. Chcę również opisać zachowania związane z obsługą wysyłania przez delegata i sprawić, aby metody obsługi były również „ogólne”.
Wymagania projektowe są następujące:
Utwórz obiekt, który może być zawarty w winformie, aby obsługiwać przetwarzanie wielu podraportówUtwórz instancję i skonfiguruj obiekt w winformieZbuduj tabelę wysyłki lub instrukcję switch / case w winformiePodaj wszystkie metody obsługi specyficznych wymagań przeglądarki raportów tej winformyCelem jest stworzenie obiektu, który może być testowany osobno i wykonany jako odporny, a także nie trzeba wycinać i wklejać koła i wykonywać wielu ręcznych poprawek dla każdej nowej winformy.
Wydaje mi się, że ktoś znalazł lepszy projekt niż obecnie.
Utwórz obiekt, który może być zawarty w winformie, aby obsługiwać przetwarzanie wielu podraportów
Do tej pory mam delegata na zdarzeniu ładowania formularzy lokalnych:
this.reportViewer1.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(LocalReport_SubreportProcessing);
które jest obsługiwane przez instrukcję switch w metodzie * LocalReport_SubreportProcessing *.
Treść metody zawiera instrukcję 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;
}
Na bok:Moim zdaniem przełącznik jest w większości czytelny dla człowieka w porównaniu z alternatywą, którą rozważałem. Rozważałem użycie skrótu z nazwą raportu jako klucza i danych wywołania funkcji jako wartości. Jednak tak naprawdę nie wiedziałem, jak to zrobić i pomyślałem, że trudniej będzie komuś zrozumieć.
Następnie następuje wywołanie funkcji, która zmienia układ informacji przekazanych z wywołania funkcji w instrukcji switch:
private static void runSubAlternatePart(SubreportProcessingEventArgs e1, String commonReportKey, GetAlternatePart myAP)
{
myAP.AlgorithmInterface(commonReportKey, e1);
}
Ta zmiana jest zdecydowanie jąkaniem kodu, ale jest pozornie niezbędna w stosunku do wzorca strategii, który próbuję wdrożyć:
abstract class IStrategy
{
public abstract void AlgorithmInterface(String searchParam, SubreportProcessingEventArgs e);
}
Oto konkretne wdrożenie strategii dla jednego ze sprawozdań:
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]));
}
}
}
W każdym razie moim pragnieniem jest, aby nie musieć wielokrotnie przekazywać tej samej logiki między raportami, ponieważ mam wiele raportów z wieloma podraportami.
Chciałbym, aby biblioteka korzystała z klasy do dynamicznego tworzenia części środkowych, w których występuje jąkanie, i chciałbym przekazać funkcję „anonimową”, która faktycznie implementuje szczegółowe połączenie podraportu z odpowiadającym mu źródłem danych.
W przypadku pojedynczego raportu z podraportami, a nawet kilku jednorazowych raportów, to, co robię, jest w porządku, ale jak można je uczynić mniej ręcznym, solidniejszym i bardziej testowalnym?
Moje środowisko to Visual Studio 2008 z celem .NET 3.5; wydaje się, że istnieje różnica w sposobie deklarowania klas abstrakcyjnych i ich kompilacji.