Создать кастомизируемый тип из GetType?

#c# #generics #reflection

#c# #дженерики #отражение

Вопрос:

Объясненный ниже во фрагменте кода, я не могу понять синтаксис для этого:

 object tcsObject = new TaskCompletionSource<Apple>();
Apple apple = new Apple();

// How do I do this?
TaskCompletionSource<apple.GetType>() tsc = tscObject as TaskCompletionSource<apple.GetType>()

 

Редактировать
Следует отметить, что конкретная проблема, которую я пытаюсь решить, заключается в том, как выполнить это приведение дженериков, изначально не зная, что тип — это Apple. Тип может в конечном итоге быть любым, поэтому я хочу выполнить эту операцию из того, что возвращается через GetType .

Комментарии:

1. Вы можете использовать отражение, но проблема в том, что весь дальнейший код, который будет его использовать, также должен использовать отражение. Не лучше ли было бы замаскировать это под TaskCompletionSource<object> ?

2. Вы не можете передавать динамические типы в обобщенные. Дженерики — это концепция времени компиляции, GetType выполняется во время выполнения

3. Вы не можете. Компилятору необходимо знать тип каждой переменной во время компиляции . Либо с известным фиксированным типом, либо с вашим собственным параметром универсального типа в области видимости.

4. В этом примере тип всегда Apple так почему бы вам просто не использовать TaskCompletionSource<Apple> ?

5. Вы могли бы создать метод со всем кодом в нем, который должен использовать TaskCompletionSource<T> , а затем использовать отражение для вызова этого метода, тогда вы, по крайней мере, минимизировали бы количество необходимых отражений.

Ответ №1:

Если вы не возражаете пожертвовать безопасностью типов во время компиляции, вы могли бы использовать Convert.ChangeType() dynamic ключевое слово and следующим образом:

 static dynamic ConvertTo(this object source, Type targetType)
{
    return (dynamic)Convert.ChangeType(source, targetType)
}

public void YourActualCode()
{
    object tcsObject = new TaskCompletionSource<Apple>();
    Apple apple = new Apple();

    TaskCompletionSource<Apple> tsc = ConvertTo(tscObject, typeof(TaskCompletionSource<Apple>))
}
 

Самое приятное в этом подходе то, что вы можете отложить определение типа параметра до времени выполнения:

 var wrapperType = typeof(TaskCompletionSource<>);
var paramType = typeof(Apple);

var concreteType = wrapperType.MakeGenericType(paramType);

TaskCompletionSource<Apple> tsc = ConvertTo(tscObject, concreteType);
 

Комментарии:

1. Спасибо вам за это. То, что я действительно пытался выяснить, это как создать универсальный тип из GetType. В частности, яблоко. GetType. Поскольку проблема, с которой я борюсь, заключается в том, что я не знаю, каким типом может оказаться Apple.

2. @rygo6 тогда вы определенно хотите что-то вроде typeof(TaskCompletionSource<>).MakeGenericType(apple.GetType()) 🙂