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)
的函数,它给出了结果的统计信息,它对所有处理程序都是通用的(因此,为了避免重复,我把它放在那里)。
代码现在更清晰了,它现在不使用任何泛型或重写方法。然而,我仍然很好奇我应该如何处理这样的案例,并将尝试用一个更简单的例子在另一个问题中表述它。
谢谢大家的意见,真的很感激!
我想我现在有点困惑,但我似乎无法解决这个问题。
我有一个接口 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)
的函数,它给出了结果的统计信息,它对所有处理程序都是通用的(因此,为了避免重复,我把它放在那里)。
代码现在更清晰了,它现在不使用任何泛型或重写方法。然而,我仍然很好奇我应该如何处理这样的案例,并将尝试用一个更简单的例子在另一个问题中表述它。
谢谢大家的意见,真的很感激!