2016-09-23 40 views
2

我有泛型的問題。我寫了一個泛型類。我從這個類中派生出其他類。使用來自非泛型類的泛型

最後我想在另一個類中使用這個派生類,但我還沒有找到工作解決方案如何讓它工作。

這裏是我的簡單的例子:

// Generic base class 
public class Information<T> 
{ 
    public T StatusCode; 
    public bool Changed; 
} 

public class Status1 : Information<Status1.Codes> 
{ 
    public enum Codes { None = 0, } 
    public string AdditionalStatusInformation; 

    public Status1() 
    { 
     StatusCode = Codes.None; 
    } 
} 

public class Status2 : Information<Status2.Codes> 
{ 
    public enum Codes { OK = 0, } 

    public Status2() 
    { 
     StatusCode = Codes.OK; 
    } 
} 

一切好爲止。我使用Json發送和閱讀這些信息,這種方法適用於接收器和發射器。適用於Status1和Status2類。

最後,我有通用的ErrorReporter類,我想使用我的Status1或Status2類。似乎這是不可能的。

public class ErrorReporter<T> where T : Information<T> 
{ 
    public readonly T Info = Activator.CreateInstance<T>(); 

    public void Update() 
    { 
     if (Info.Changed) 
     { 
      Console.WriteLine(Info.StatusCode.ToString()); 
      Console.WriteLine(JsonConvert.SerializeObject(Info)); 
     } 
    } 
} 

似乎沒有辦法正確實例化這個類。

我嘗試了這些

new ErrorReporter<Status1>() 
new ErrorReporter<Status1.Codes>() 
new ErrorReporter<Information<Status1.Codes>() 

我越來越

The type 'TestApp.Program.Status1' cannot be used as type parameter 'T' in 
the generic type or method 'TestApp.Program.ErrorReporter<T>'. 
There is no implicit reference conversion from 'TestApp.Program.Status1' to 
'TestApp.Program.Information<TestApp.Program.Status1>'. 

或類似的錯誤消息。

我可能應該將我的ErrorReporter類移動到Information類。

但是,從我的ErrorReporter類實例化新對象的正確方法是什麼?它甚至有可能嗎?

回答

0

您需要T來自Information<T>,這不是你想要的。

我想你需要這個,你需要提供爲通用類型參數:

public class ErrorReporter<T, S> where T : Information<S> 
{ } 

一點點額外的,你可以刪除反射調用:

public class ErrorReporter<T, S> where T : Information<S>, new() 
{ 
    public readonly T Info = new T(); 
} 
0

問題是你試圖使用T有兩個目的:

  • 狀態碼的來源(你打電話StatusCode就可以了)
  • 類型的狀態代碼(它是Information<T>類型參數)

現在你可以只是讓ErrorReporter一般有兩種類型的參數,而不是:

public class ErrorReporter<TSource, TCode> where TSource : Information<TCode> 
{ 
    public readonly TSource Info = Activator.CreateInstance<TSource>(); 

    public void Update() 
    { 
     if (Info.Changed) 
     { 
      Console.WriteLine(Info.StatusCode.ToString()); 
      Console.WriteLine(JsonConvert.SerializeObject(Info)); 
     } 
    } 
} 

那麼你可以使用:

new ErrorReporter<Status1, Status1.Codes>() 

或者你可以米AKE它在短短的代碼類型通用的,但要避免被反射構造來源:

public class ErrorReporter<T> 
{ 
    // You could expose this as a property if you want. I would 
    // advise against exposing it as a field 
    private readonly Information<T> source; 

    public ErrorReporter(Information<T> source) 
    { 
     this.source = source; 
    } 

    public void Update() 
    { 
     if (Info.Changed) 
     { 
      Console.WriteLine(source.StatusCode.ToString()); 
      Console.WriteLine(JsonConvert.SerializeObject(source)); 
     } 
    } 
} 

,構建它:

var reporter = new ErrorReporter<Status1.Codes>(new Status1()); 
+0

多虧了你們倆。我現在看到我的錯誤... – itix