C # Generic T Class TypeOf, возможно ли это? - PullRequest
2 голосов
/ 16 апреля 2011

У меня есть общий класс. 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> и т. Д. *

EDIT:

Вот что я пытаюсь сделать, фактический код:

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

изображение макета

Спасибо.

Ответы [ 5 ]

3 голосов
/ 16 апреля 2011

Если вы собираетесь вызывать ту же операцию на экземпляре '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 голос
/ 16 апреля 2011

Это зависит от того, как вы собираетесь использовать общие типы в дальнейшем.string, int и decimal не имеют общего базового типа, кроме object, но они имеют некоторые общие интерфейсы, так что вы можете выбрать что-то вроде Class<IComparable>, если вы хотите отсортировать их позже.Или вы можете объявить общие ограничения, если вы хотите использовать несколько интерфейсов:

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

Но то, что вы, похоже, просите, кажется невозможным.Вся предпосылка обобщения заключается в том, чтобы установить тип во время разработки.

1 голос
/ 16 апреля 2011

Что вы хотите сделать с х позже? Кроме того, если вы можете создать его так, чтобы x всегда был экземпляром некоторого базового класса, вы можете просто привести его к базовому классу.

0 голосов
/ 16 апреля 2011

Я думаю, что лучший способ сделать это переключение было бы на самом деле реализовать отдельные методы для ваших различных типов, и переключаться на уровне пользовательского интерфейса.

Например

public ReportResult<int> GetReportDataCount(ReportProcedureNameEventArg procedureNameEventArg)

public ReportResult<DateTime> GetReportDataDate(ReportProcedureNameEventArg procedureNameEventArg)

public void GetReportDataList(ReportProcedureNameEventArg procedureNameEventArg)

«Список» - это тот, который действительно отбрасывает меня, потому что он возвращает ноль, иначе я бы сказал, что-то вроде public ReportResult<T> GetReportData<T>(ReportProcedureNameEventArg procedureNameEventArg) where T:struct (и затем применять типы программно).

Если вы хотите попробовать это с динамикой, я думаю, вы могли бы заставить это работать в основном, выполнив типизацию с использованием утилит с помощью ReportResult, но это может запутатьсяваш режим списка в миксе тоже.

0 голосов
/ 16 апреля 2011

Мое мнение

Если результат всегда используется для вызова одних и тех же членов класса (классов), то можно создать интерфейс и реализовать его для различных классов и получитьрезультат в качестве интерфейса.Таким образом, вы сможете использовать разные классы, но некоторые элементы интерфейса, реализованные в этих классах

...