C#Generic T Class TypeOf,这可能吗?

时间:2011-04-16 01:42:11

标签: c# generics type-conversion gettype

我有一个通用的类。 Class<T>并且根据调用代码中的switch语句,它可以是class<int> class<string> class<decimal>

返回此方法会将其作为对象返回,因为调用代码在设置之前不知道它是什么。

一旦我从函数中取回对象,有没有办法做到这一点?

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

感谢。

5 个答案:

答案 0 :(得分: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();
}

答案 1 :(得分:1)

以后你想用x做什么?此外,如果您可以构建它以使x始终是某个基类的实例,则可以将其强制转换为基类。

答案 2 :(得分:1)

这取决于您以后打算如何使用泛型类型。 stringintdecimal除了object之外没有共同的基本类型,但是它们共享一些接口,因此您可以选择类似Class<IComparable>的内容你想稍后对它们进行排序。或者,如果要使用多个接口,则可以声明泛型约束:

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

但是你似乎要求的东西似乎不可能。泛型的整个前提是在设计时设置类型。

答案 3 :(得分:0)

我的意见

如果结果始终用于调用类的相同成员,则可以创建一个接口并将其实现到不同的类,并将结果作为接口。 这样,您就可以使用不同的类,但是在这些类中实现的接口的一些相同成员

答案 4 :(得分:0)

我认为执行此切换的最佳方法是实际为不同类型实现单独的方法,并在UI层切换。

例如

public ReportResult<int> GetReportDataCount(ReportProcedureNameEventArg procedureNameEventArg)

public ReportResult<DateTime> GetReportDataDate(ReportProcedureNameEventArg procedureNameEventArg)

public void GetReportDataList(ReportProcedureNameEventArg procedureNameEventArg)

“List”是一个真正抛弃我的,因为它返回null,否则我会说做类似的事情 public ReportResult<T> GetReportData<T>(ReportProcedureNameEventArg procedureNameEventArg) where T:struct(然后以编程方式强制执行类型)。

如果你想用动态尝试它,我认为你可以通过使用ReportResult进行鸭子打字来实现这种方式,但是混合中的列表模式也可能会变得混乱。