1

我在多态基类中使用泛型覆盖方法的语法有问题。

这是用于报告引擎的基本架构;我在一个基类中有两个虚拟方法和大量从基类派生的对象,它们覆盖了这些方法。

在客户端代码中,调用了一个报表工厂对象,该对象根据传入的字符串以及用作参数的对象数组实例化其中一个对象。方法的字符串名称来自数据库并位于多选列表中,因此用户可以选择任意数量的报告来运行。

现在的需求是创建 PDF 文档,这很容易做到,因为通用方法只有一个已知类型。我想做的是扩展它的用处并返回任何类型的列表。

这是我的虚拟方法的签名。第一个是强类型的,我可以完美地工作,第二个,我有问题。他们来了:

    /// <summary>
    /// Virtual method to run report from a Word mail merge template
    /// </summary>
    /// <param name="Template">Word mail merge template name</param>
    /// <returns>PDF Document</returns>
    public virtual PdfDocument RunReportPDFOutFromWordTemplate( string TemplateName )
    {
        try
        {
            return new PdfDocument();
        }
        catch( Exception )
        {
            throw;
        }
    }

    /// <summary>
    /// Virtual method to run report outputting a generic list
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public virtual List<T> RunReportListOut<T>()
    {
        try
        {
            return new List<T>();
        }
        catch( Exception )
        {
            throw;
        }
    }

然后在我的代码中,我通过调用我的 ReportFactory 类来调用该对象。首先是 ReportFactory 类,然后是调用代码:

    public static class ReportFactory
{
    /// <summary>
    /// Get an object from the Report Factory
    /// </summary>
    /// <param name="ObjectName">Name of the Object</param>
    /// <param name="ParamList">List of parameters the object constructor is expecting</param>
    /// <returns></returns>
    public static ReportBase GetObject( string ObjectName, object[] ParamList )
    {
        try
        {
            return (ReportBase)Activator.CreateInstance( Type.GetType( Utils.GetCurrentNamespaceName() + "." + ObjectName ), ParamList );
        }
        catch( Exception )
        {
            throw;
        }
    }
}

现在对于调用代码:

                        ParamList = new object[] { r.Name, r.MethodPointer, this.dpStartDate.SelectedDate, this.dpEndDate.SelectedDate, this.AppData.ActivePatient };
                    rb = ReportFactory.GetObject( r.MethodPointer, ParamList );

                    PdfDocument pdfDoc = rb.RunReportPDFOutFromWordTemplate( ConfigurationManager.AppSettings[ "ReportTemplateLocation" ].ToString() + r.MethodPointer + ConfigurationManager.AppSettings[ "ReportTemplateType" ].ToString() );

有效方法的代码在这里并不真正相关,我不想通过发布它来浪费任何人的时间。它适用于我需要它做的事情。

问题是我希望能够使用相同的报告工厂返回一个列表。当我覆盖我的方法时,我收到以下错误:Cannot implicitly convert type 'System.Collections.Generic.List<FMCNA_Model.Cycle>' to 'System.Collections.Generic.List<Cycle>

这是覆盖的代码和辅助方法:

    public override List<Cycle> RunReportListOut<Cycle>()
    {
        try
        {
            List<Cycle> CycleList = this.GetCycleList();
            return CycleList;
        }
        catch( Exception )
        {
            throw;
        }
    }

    private List<Cycle> GetCycleList()
    {
        try
        {
            return Cycle.PatientForDateRange( this.CurrentPatient.PatientIDInternal, this.StartDate, this.EndDate );
        }
        catch( Exception )
        {
            throw;
        }
    }

我很难过如何做到这一点。抱歉这个问题太长了,我认为最好把所有内容都集中在覆盖语法上。

谢谢,

麦克风

4

2 回答 2

1

正如 SLaks 所说,您在尝试使用名为的类型参数T声明泛型虚拟方法时遇到了问题- 但随后您尝试使用另一个泛型方法Cycle作为类型参数来覆盖它。这真的不是你的意思。泛型方法意味着调用者可以指定类型参数 - 而您可能只想返回一个List<Cycle>.

我强烈怀疑您应该有一个泛型类型,并带有一个使用该类型参数的方法声明。例如:

public abstract class Report<T>
{
    public abstract List<T> RunReportListOut();
}

然后

public class CycleReport : Report<Cycle>
{
    public override List<T> RunReportListOut()
    {
        ...
    }
}

如果您拥有两种类型,则以不同的方式命名它们会更简洁......然后您需要在您的方法中添加一个转换。或者,只需将这两种类型合并为一种,这可能会更干净。

此外,正如我在评论中指出的那样,您应该删除您的 try/catch 块。它们都没有任何好处,而且它们会弄乱你的代码——目前在你的方法的主体中,你总共有 6 行“主体”代码和 35 行毫无意义的 try/catch。一旦你删除了这些,很明显你的GetCycleList辅助方法也毫无意义。你可以写:

public override List<Cycle> RunReportListOut()
{
    return Cycle.PatientForDateRange(this.CurrentPatient.PatientIDInternal,
                                     this.StartDate, this.EndDate);
}
于 2012-11-27T19:35:07.137 回答
1
public override List<Cycle> RunReportListOut<Cycle>()

这将创建一个常规泛型方法,其类型参数恰好命名为Cycle
它与 ; 没有什么不同public override List<T> RunReportListOut<T>()。类型参数仍然可以是任何类型。

您尝试做的事情是完全不可能的;您不能用非泛型方法覆盖泛型方法。

于 2012-11-27T19:38:01.090 回答