динамическое создание экземпляра c # с использованием отражения

#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 в метод с содержащимся в нем кодом. Это сработало.