Получить параметр типа T из созданного экземпляра System.Type? - PullRequest
1 голос
/ 29 марта 2009

У меня есть System.Type определенного объекта, но мне нужно передать его как параметр типа T другому методу ... это возможно? Или я потерялся в более широкой картине?

Ответы [ 5 ]

1 голос
/ 29 марта 2009

То, что вы просите сделать, в .Net невозможно. Параметры типа являются операцией типа компиляции в .Net (C # и VB). Экземпляр System.Type, хотя и является конструкцией времени выполнения. Любые запросы о реальном типе System.Type должны выполняться во время выполнения. Таким образом, решения не совместимы.

Например:

public void DoSomething<T>(T value) {
  // Do something with a value of type T
}

public Example1() {

  DoSomething(42);  // Calls DoSomething<int>
  Type t1 = typeof(int);
  DoSomething(t1);  // Calls DoSomething<Type>

  object o1 = 42;
  Type t2 = o1.GetType();
  DoSomething(???)  // No way to call DoSomething<int> here without some
                    // wild reflection because the call to DoSomething is
                    // established at compile type where t2 is established
                    // at runtime
}
1 голос
/ 29 марта 2009

Это невозможно. Если подумать, параметр типа разрешается во время компиляции, тогда как тип System.Type разрешается отражением во время выполнения.

Теперь, сказав, что это невозможно, это возможно с помощью отражения. Если вы создаете класс с отражением, вы можете передать System.Type в качестве параметра, но, вероятно, стоит просто изменить дизайн того, что вы пытаетесь сделать.

РЕДАКТИРОВАТЬ: Вот несколько идей для редизайна.

Откуда взялся System.Type? Не могли бы вы передать его как параметр типа, чтобы он мог быть передан через?

Если нет, то не могли бы вы сделать адаптер, который будет обрабатывать известные типы, которые будут использоваться? Возможно, оператор switch, который преобразует System.Type в правильный тип общего вызова? Все быстрее, чем отражение.

0 голосов
/ 29 марта 2009

Что вы обычно делаете, так это перегрузок для универсального метода специально для операций такого типа. E.g.:

Load<T>();
Load(Type type);
0 голосов
/ 29 марта 2009

Рассмотрите возможность использования альтернативного дизайна. Универсальные типы предназначены для статического разрешения во время компиляции.

Тем не менее, это возможно сделать. Вам нужно прибегнуть к размышлению:

public class TypeReporter<T> {
    public TypeReporter() {
        Console.WriteLine("this type is: {0}", typeof(T));
    }

    // other methods
}

public class StackOverflow694683 {
    static void Main() {
        string n = "..."; // Pick a type, such as System.String.
        Type arg = Type.GetType(n);
        Type genericClass = typeof(TypeReporter<>);
        Type createdClass = genericClass.MakeGenericType(arg);

        // Result is of TypeReporter<T> type. Invoke desired methods.
        object result = Activator.CreateInstance(createdClass);
    }
}
0 голосов
/ 29 марта 2009

Вы можете сделать это с помощью отражения.

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

DoSomething(yourObject.GetTaype());
...