2011-04-16 74 views
2

我有一個通用的類。 Class<T>並根據在調用代碼switch語句也可以是class<int>class<string>class<decimal>C#通用T類TypeOf,這可能嗎?

的返回,因爲調用代碼不知道它是什麼,直到它被設置在此之後返回它作爲一個對象的方法。

有沒有辦法做到這一點,當我從該函數返回對象?

load(object result) 
{ 
    Type t = result.GetType().GetGenericArguments()[0]; 

    Class<t> x = (Class<t>) result; 
} 

或者我必須設置一個檢查來檢查它可能的每種類型。如果int然後Class<int>,等...

編輯:

這裏就是我試圖做的,實際代碼:

public class ReportResult<TP> 
{ 
    public ReportResult() 
    { 
     ReportHeaders = new List<ReportHeader>(); 
     ReportViews = new List<IDataAttributeChild<TP>>(); 
    } 

    public List<ReportHeader> ReportHeaders {get;set;} 
    public List<IDataAttributeChild<TP>> ReportViews {get;set;}   
} 

BAL

public object GetReportData(ReportProcedureNameEventArg procedureNameEventArg) 
    { 
     object result = null; 

     switch (procedureNameEventArg.SelectedNode.Class) 
     { 
      case ReportClass.Count: 
       var r = new ReportResult<int> 
          { 
           ReportViews = GetCountByReport(procedureNameEventArg), 
           ReportHeaders = GetReportHeaders(procedureNameEventArg.SelectedNode.ReportViewId) 
          }; 

       result = r; 
       break; 
      case ReportClass.List: 
       break; 
      case ReportClass.Date: 
       var r = new ReportResult<datetime> 
          { 
           ReportViews = GetDateSummaryReport(procedureNameEventArg), 
           ReportHeaders = GetReportHeaders(procedureNameEventArg.SelectedNode.ReportViewId) 
          }; 

       result = r; 
       break; 
      default: 
       throw new ArgumentOutOfRangeException(); 
     } 
     return result; 
    } 

的GUI

public void LoadTreeResult(object result) 
    { 
     Type t = result.GetType().GetGenericArguments()[0]; 

     ReportResult<?> fff = (ReportResult<?>)result; 


     dgResult.Columns.Clear(); 

     foreach (var header in result.ReportHeaders) 
     { 
      dgResult.Columns.Add(
        new DataGridTextColumn 
        { 
         Header = header.Header, 
         Binding = new Binding(header.Binding) 
        }); 
     } 

     // This would also be a switch depending on a property coming 
     // back to now what class to cast to in order to populate the grid. 
     List<ReportCountByView> d = new List<ReportCountByView>(); 

     foreach (var reportCountByView in result.ReportViews) 
     { 
      d.Add((ReportCountByView)reportCountByView); 
     } 

     dgResult.ItemsSource = d; 
    } 

這是一個類模型的佈局,以防它可能有所幫助。

enter image description here

image of layout

感謝。

+1

有時候,當我發現自己處於這個位置時,答案就是使該函數成爲一個通用本身(從而使'object result'具有強類型,然後可以執行Class 等等)。也許如果你發佈了更多的代碼,我們可以看到這是否適用?否則,我認爲你的選擇可能會做一個很大的「if」塊,或者可能是一些動態的瘋狂。 – Brook 2011-04-16 01:56:02

+0

只需發佈代碼和圖表。 – nitefrog 2011-04-16 02:10:42

+0

這看起來過於複雜,甚至不清楚你想要完成什麼。你只是試圖用給定類型的值填充樹? – Jason 2011-04-16 07:11:14

回答

1

你以後想用x做什麼?另外,如果你可以將它設計成x始終是某個基類的實例,那麼你可以將它轉換爲基類。

+0

問題在於這個類包含一個List >和List

,這可以是我拋出的任何對象。 T設置數據類型,因爲根據我返回的內容可以改變。一旦我投了對象,我將訪問列表並將它們綁定到樹和數據網格。回來的數據有一個要求,可以是任何事情。我需要退回到這個類,因爲它是一個擁有其他對象的類。 – nitefrog 2011-04-16 01:50:24

0

我的意見的

如果結果總是被用來調用類(ES)的相同的成員,則可以使一個接口,並將其落實到不同的類別和得到的結果作爲接口。 這樣你就可以使用不同的類,但在這些類中實現的接口的一些相同成員

1

這取決於你打算以後如何使用泛型類型。 string,intdecimalobject之外沒有其他共同的基本類型,但它們確實共享一些接口,因此如果您想稍後對它們進行排序,則可以選擇諸如Class<IComparable>之類的內容。或者,如果您想使用多個接口,則可以聲明通用約束條件:

Class<T> where T : IEquatable<T>, IComparable<T>, IFormattable // and so on... 

但是看起來您要求的似乎不可行。泛型的整個前提是在設計時設置類型。

+0

我剛剛對這個問題發佈了一個更好的解釋。謝謝。 – nitefrog 2011-04-16 02:11:57

3

如果打算在解析它後調用實例'x'上的相同操作,則可以考慮使用接口,這將允許您定義對象執行的方法(和屬性)而不定義它的類型。

你的代碼可能那麼最終看起來像這樣

public interface IMyInterface 
{ 
    void PerformOperation(); 
} 

public class MyGeneric<T> : IMyInterface 
{ 
    T Value {get;set;} 
    MyGeneric(T val) 
    { 
    Value = val; 
    } 

    void PerformOperation 
    { 
    Console.WriteLine("T is {0}", typeof(T)); 
    Console.WriteLine("Value is {0}", Value); 
    } 
} 

public void main(string[] args) 
{ 
    IMyInterface inst = null; 
    switch (args[0]) 
    { 
    case "string": 
     inst = new MyGeneric("hello"); 
     break; 
    case "int": 
     inst = new MyGeneric(7); 
     break; 
    case "decimal" 
     inst = new MyGeneric(18.9M); 
     break; 
    } 

    inst.PerformOperation(); 
} 
0

我覺得做這個開關最好的辦法就是實際執行單獨的方法,爲不同類型,並在UI層交換機。

例如

public ReportResult<int> GetReportDataCount(ReportProcedureNameEventArg procedureNameEventArg)

public ReportResult<DateTime> GetReportDataDate(ReportProcedureNameEventArg procedureNameEventArg)

public void GetReportDataList(ReportProcedureNameEventArg procedureNameEventArg)

「列表」 一個是一個真正拋出我送行,因爲它返回null,否則我會說這樣做像 public ReportResult<T> GetReportData<T>(ReportProcedureNameEventArg procedureNameEventArg) where T:struct(然後以編程方式強制執行類型)。

如果你想用動態來試試它,我認爲你可以通過使用ReportResult進行鴨子打字來使它工作,但是它也可能會混亂你的List模式。