C# 使用泛型调用重写的方法

C# Use Generics to Call Overridden Method

我想我现在有点困惑,但我似乎无法解决这个问题。

我有一个接口 ILinkHandler<T> 和其他 4 个处理程序 类(从该接口继承),它们验证 link 的不同结构。在该界面中,我有一个 Task<List<T>> Validate() 函数,用于验证 links 和 returns 结果的 Task>。根据 T,我在 Validate() 上 return 一个不同的模型(我有 4 个不同的模型)。

我的控制台应用程序执行以下操作。它调用每个 link 类型的 Task<List<T>> Validate(); 方法并在得到结果后创建一些日志(注意 Validate()async)。每个日志都有点不同,因为模型不同,所以我覆盖了一个名为 WriteResults(ModelX results, string name) 的方法和 ModelX 类型(见问题结尾,我发布了 2 个示例),我做了一些不同的事情(不重要我认为在这个范围内,但如有必要,我可以提供详细信息)。此方法不是异步的。

我想使用泛型和我的接口创建一个方法 (ValidateModel<T>),该方法处理从模型类型正确调用覆盖方法 WriteResults 并调用 Validate() 接口中的方法。

下面的代码是我所做的,但 if 部分类似于我目前在 main 中的部分,我想避免。

public void ValidateModel<T>(ILinkHandler<T> handler, string name) where T : class
{
    Console.WriteLine($"Validating {name}");
    var results = handler.Validate();

    if (typeof(T) == typeof(InternalLinksModel))
    {
        WriteResults(results.Result as List<InternalLinksModel>, name);
    }
    else // continue with other models
}

这是我的主要内容:

private static void Main(string[] args) 
{
    Console.WriteLine("Validating External_Links");
    var resultsForExternalLinks = ExternalLinkHandler.Validate();
    WriteResults(resultsForExternalLinks.Result, "External_Links");

    Console.WriteLine("Validating Image_Links");
    var resultsForImageLinks = ImageLinkHandler.Validate();
    WriteResults(resultsForImageLinks.Result, "Image_Links");

// and so on
}

如果可能的话,我想要更多这样的东西,但它无法编译:

public void ValidateModel<T>(ILinkHandler<T> handler, string name) where T : class
{
    Console.WriteLine($"Validating {name}");
    var results = handler.Validate();

    WriteResults<T>(results.Result as List<T>, name);
}

这里是 WriteResults 的定义(注意,因为它被覆盖了,所以我有 4 个方法,它们的签名在列表类型中发生了变化):

private void WriteResults(List<InternalLinksModel> results, string filename) { // Logs results into folder to display in jenkins }

private void WriteResults(List<PdfLinksModel> results, string filename) { // Logs results into folder to display in jenkins }

// and so on

编辑:添加更多代码

接口:

public interface ILinkHandler<T>
{   
    Task<List<T>> Validate();
}

Handler示例Class继承接口:

public class InternalLinkHandler : ILinkHandler<InternalLinksModel>
{
    public List<InternalLinksModel> InternalLinks = new List<InternalLinksModel>();

    public async Task<List<InternalLinksModel>> Validate()
    {
        // Here set up my tests, call tasks that modifies InternalLinks List and I await for its results
        return InternalLinks 
    }

Main Class(名为 XmlLinkCheckerValidator)我的代码当前运行(并且有效)的位置:

public class XmlLinkCheckerValidator
{
    // References to all modes
    public ExternalLinkHandler ExternalLinkHandler => new ExternalLinkHandler();
    public ImageLinkHandler ImageLinkHandler => new ImageLinkHandler();
    public InternalLinkHandler InternalLinkHandler => new InternalLinkHandler();
    public PdfLinkHandler PdfLinkHandler => new PdfLinkHandler();

    public void ValidateIPack()
    {
        InitialSetup();

        Console.WriteLine("Validating External_Links");
        var resultsForExternalLinks = ExternalLinkHandler.Validate();
        WriteResultsForIPacksInCsv(resultsForExternalLinks.Result, "External_Links");

        Console.WriteLine("Validating Image_Links");
        var resultsForImageLinks = ImageLinkHandler.Validate();
        WriteResultsForIPacksInCsv(resultsForImageLinks.Result, "Image_Links");

        Console.WriteLine("Validating Internal_Links");
        var resultsForInternalLinks = InternalLinkHandler.Validate();
        WriteResultsForIPacksInCsv(resultsForInternalLinks.Result, "Internal_Links");

        // Console.WriteLine("Validating Pdf Links");
        // var results = XmlLinkExtractorFromIPacks.PdfLinkHandler.Validate();
        // WriteResultsForIPacks(results, "Pdf Links");
    }

    private void WriteResultsForIPacksInCsv(List<InternalLinksModel> results, string filename) { logging results }

    private void WriteResultsForIPacksInCsv(List<ExternalLinksModel> results, string filename) { logging results }

    private void WriteResultsForIPacksInCsv(List<ImageLinksModel> results, string filename) { logging results }

    private void WriteResultsForIPacksInCsv(List<PdfLinksModel> results, string filename) { logging results }

    private void WriteResultsForIPacksInCsv(List<InternalLinksModel> results, string filename) { logging results }

我终于重构了我所有的代码,看起来清晰多了。正如我所说,一开始,我觉得我有点混乱,这一切都源于我做出的一个糟糕的设计决定。

总之,我加了一个新方法,WriteResults(string filename)。为此,我实现了该方法并从我的 "Main" class 中删除了覆盖的方法 (WriteResultsForIPacksInCsv(List<WhateverModelIHad> results, string filename))。从那以后,我将接口中的 Validate 方法签名更改为 Task<List<PossibleResults>> Validate(),并且由于每个模型都有它的共同点,所以我删除了接口中的泛型。我现在可以通过以下方式调用我的处理程序:

public void Validate(ILinkHandler handler, string filename)
{
    Console.WriteLine($"Validating {filename}");
    var results = handler.Validate();
    SetUpResultsStatistics(results.Result, $"{filename}_Statistics");
    handler.WriteResults(filename);
}

我创建了一个名为 void SetUpResultsStatistics(List<PossibleResults> results, string filename) 的函数,它给出了结果的统计信息,它对所有处理程序都是通用的(因此,为了避免重复,我把它放在那里)。

代码现在更清晰了,它现在不使用任何泛型或重写方法。然而,我仍然很好奇我应该如何处理这样的案例,并将尝试用一个更简单的例子在另一个问题中表述它。

谢谢大家的意见,真的很感激!