在c#中实现泛型接口的类工厂
本文关键字:工厂 泛型接口 实现 | 更新日期: 2023-09-27 18:16:58
我需要创建一个处理文件的通用方法。根据需要对文件执行的操作,应该使用特定的类。我使用ASP和c#。文件上传后,我对文件进行分析,创建分析结果对象,并根据该对象向用户显示分析结果。用户是否读取分析结果并继续(单击按钮)。如果他这样做,那么我将获取该分析结果对象并基于它执行操作(处理)。我将处理结果显示给用户。
根据一些查询参数(为了简单起见),文件应该由不同的类处理。处理器需要特定于分析器具体实现的分析结果(分析一个文件的结果可能包括自定义类的列表,不同文件分析的结果可能包含其他特定字段)。处理器需要这些特定于实现的细节来完成它的工作。
我尝试创建一个通用项目,但是卡住了。
工厂中的magicId是一个查询参数,指定应该使用哪个类来解析/分析文件。
是否有一种方法来创建一个工作工厂的类,所有实现一个泛型接口?
abstract class AnalysisResult
{
}
interface IAnalyzer<TAnalysisResult>
where TAnalysisResult : AnalysisResult
{
TAnalysisResult PerformAction(string input);
}
class ConcreteAnalysisResult : AnalysisResult {
public int SpecificProperty { get; set; }
}
class ConcreteAnalyzer : IAnalyzer<ConcreteAnalysisResult>
{
public ConcreteAnalysisResult PerformAction(string input)
{
return new ConcreteAnalysisResult() { SpecificProperty = input.Length };
}
}
class AnAnalyzerFactory
{
IAnalyzer<AnalysisResult> CreateByMagicId(int magicId)
{
return new ConcreteAnalyzer();
}
}
声明TAnalysisResult
为协变。有关详细信息,您可以查看协方差和逆变
interface IAnalyzer<out TAnalysisResult> // note out keyword
where TAnalysisResult : AnalysisResult
{
TAnalysisResult PerformAction(string input);
}
虽然您可以通过使用类型协方差来修复代码,但是在代码中仍有一个地方需要根据分析器的具体类型进行分派。这是次优的,因为使用泛型隐藏了一些稍后需要"解除隐藏"的东西(例如,为了获得SpecificProperty
属性)。
// The following removes generics from your code
abstract class AnalysisResult {
}
interface IAnalyzer {
AnalysisResult PerformAction(string input);
}
class ConcreteAnalysisResult : AnalysisResult {
public int SpecificProperty { get; set; }
}
class ConcreteAnalyzer : IAnalyzer {
public AnalysisResult PerformAction(string input) {
return new ConcreteAnalysisResult() { SpecificProperty = input.Length };
}
}
// Here is the magic that lets you process results of specific types without generics
public static void main(string[] args) {
var analyzer = new ConcreteAnalyzer();
dynamic res = analyzer.PerformAction(input);
ProcessResult(res); // This gets dispatched dynamically to the correct overload
}
private static void ProcessResult(ConcreteAnalysisResult cr) {
Console.WriteLine(cr.SpecificProperty);
}
private static void ProcessResult(SomeOtherConcreteAnalysisResult cr) {
Console.WriteLine(cr.AnoterhSpecificProperty);
}
private static void ProcessResult(AnalysisResult cr) {
// Throw an error: unexpected result type
}
请注意,上面的代码没有静态类型转换,也没有使用泛型,这在重构之后变得不必要了。