簡體   English   中英

在C#中使用通用類型實現接口的類的工廠嗎?

[英]Factory of classes implementing interfaces with generic types in C#?

我需要創建一種處理文件的一般方法。 根據文件需要執行的操作,應使用特定的類。 我使用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
}

請注意,上面的代碼沒有靜態類型轉換,並且不使用泛型,在重構之后就不再需要泛型了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM