#c# #reflection
#c# #отражение
Вопрос:
Я экспортирую отчет и заметил, что копирую много кода для каждого отчета. Я хотел бы поместить это в метод в отдельном классе, но я не уверен в том, как выполнить создание экземпляра после некоторых исследований. Мой код приведен ниже:
ActiveReport rpt = new Reports.rptContractListing_Merchant();
rpt.Run();
try
{
rpt.Run(false);
}
catch (DataDynamics.ActiveReports.ReportException eRunReport)
{
// Failure running report, just report the error to the user:
Response.Clear();
Response.Write("<h1>Error running report:</h1>");
Response.Write(eRunReport.ToString());
return;
}
XlsExport xls = new XlsExport();
xls.MinColumnWidth = (float)0.5;
xls.Export(rpt.Document, m_stream);
m_stream.Position = 0;
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("content-disposition", "inline; filename=ContractListing_Merchant.xls");
System.IO.MemoryStream m_stream = new System.IO.MemoryStream();
Response.BinaryWrite(m_stream.ToArray());
Response.End();
Вот часть, в которой я не уверен с отражением:
ActiveReport rpt = new Reports.rptContractListing_Merchant();
Другой пример:
ActiveReport rpt = new Reports.rptContractDetails();
try
{
rpt.Run(false);
}
catch (DataDynamics.ActiveReports.ReportException eRunReport)
{
// Failure running report, just report the error to the user:
Response.Clear();
Response.Write("<h1>Error running report:</h1>");
Response.Write(eRunReport.ToString());
return;
}
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "inline; filename=ContractDetails.pdf");
PdfExport pdf = new PdfExport();
System.IO.MemoryStream memStream = new System.IO.MemoryStream();
pdf.Export(rpt.Document, memStream);
Response.BinaryWrite(memStream.ToArray());
Response.End();
Комментарии:
1. Вы имеете в виду, что вам нужна функция, которая принимает объект типа
Reports.rptContractListing_Merchant
, инициирует его, а затем запускает остальную часть этой функции?2. Возможно, вы захотите показать нам код из двух отчетов, чтобы мы могли видеть, какие его части повторяются, и могли бы привести примеры кода, показывающие наилучший способ его рефакторинга. Это также было бы уместно для refactormycode.com
3. @rup Да, это то, что я собираюсь сделать.
4. У меня есть идея. Может быть, я могу просто передать объект rpt в метод.
5. :-/ Не могу поверить, что я об этом не подумал. Однако, пока я здесь, еще один момент: если вы также собираетесь передать имя файла для изменения заголовка ContentDisposition, я бы порекомендовал вам использовать System.Net.Mime . Класс ContentDisposition для генерации строки, поскольку его свойство будет экранировать имя файла, переданное в заголовке. И если вы на самом деле используете ASP.NET Затем в контроллере MVC есть
return File(...)
метод, который примет поток и имя файла и сделает все это за вас.
Ответ №1:
Я думаю, Activator.CreateInstance<T>()
это правильный путь, где T — тип отчета, который вы генерируете
Комментарии:
1. Это то, что я пытался сделать, но я не смог определить правильный синтаксис для этого.
Ответ №2:
У вас есть ряд опций, многие из которых даже не требуют отражения.
Если вы можете гарантировать, что все ваши классы отчетов имеют конструктор «по умолчанию» (без параметров), вы можете использовать generics и указать, что у универсального типа должен быть конструктор по умолчанию. Тогда вы можете просто сказать new T()
.
В противном случае вы могли бы либо использовать внедрение зависимостей для создания отчета на основе заданного типа, либо ваш метод мог бы принять сам отчет в качестве аргумента (который должен быть предоставлен вызывающим методом) и заняться оставшимся повторяющимся кодом.
Комментарии:
1. Я бы предположил, что все они наследуются от
ActiveReport
. Итак, как прокомментировал сам Брэндон, он может просто передать ActiveReport в свою функцию.
Ответ №3:
Я только что передал объект rpt в метод с содержащимся в нем кодом. Это сработало.