В C # я могу привести переменную типа объекта к переменной типа T, где T определена в переменной типа?
c#
reflection
types
theringostarrs
источник
источник
Type
переменная, вы можете использовать отражение, чтобы создать экземпляр этого типа. И затем вы можете использовать универсальный метод для возврата нужного вам типа, выводя его из параметра этого типа. К сожалению, любой метод отражения, который создает экземпляр типа, будет иметь возвращаемый типobject
, поэтому ваш обобщенныйCastByExample
метод также будет использоватьobject
. Так что на самом деле нет никакого способа сделать это, и даже если бы был, что бы вы сделали с вновь созданным объектом? Вы не могли использовать его методы или что-то еще, потому что вы не знаете его тип.object
илиdynamic
. Если вы хотите динамически загружать внешние модули, вы можете сделать так, чтобы классы имели общий интерфейс и приводили объект к этому. Если вы не контролируете сторонний код, создайте небольшие обертки и реализуйте интерфейс для этого.Ответы:
Вот пример приведения и преобразования:
Редактировать:
Некоторые люди в комментариях говорят, что этот ответ не отвечает на вопрос. Но линия
(T) Convert.ChangeType(input, typeof(T))
обеспечивает решение.Convert.ChangeType
Метод пытается преобразовать любой объект типа при условии в качестве второго аргумента.Например:
Я написал ответ с помощью дженериков, потому что я думаю, что это очень вероятный признак запаха кода, когда вы хотите преобразовать
a something
егоa something else
без обработки фактического типа. С надлежащими интерфейсами это не должно быть необходимо в 99,9% случаев. Возможно, есть несколько крайних случаев, когда речь заходит о том, что это может иметь смысл, но я бы рекомендовал избегать таких случаев.Изменить 2:
Несколько дополнительных советов:
object
илиdynamic
.источник
T
а не как таковая.Convert.ChangeType(input, typeof(T));
дает решение. Вы можете легко заменитьtypeof(T)
существующей переменной типа. Лучшим решением (если возможно) было бы предотвратить динамический тип все вместе.T
который недоступен.T
но все же вы получаете толькоobject
в качестве ссылки. хм, я нашел вопрос интересным в предположении, что у OP есть толькоType
переменная и никакой другой информации. Как будто подпись методаConvert(object source, Type destination)
:) Тем не менее, яДругие ответы не упоминают «динамический» тип. Таким образом, чтобы добавить еще один ответ, вы можете использовать «динамический» тип для хранения полученного объекта без необходимости приведения преобразованного объекта со статическим типом.
Имейте в виду, что при использовании «динамического» компилятор обходит статическую проверку типов, которая может привести к возможным ошибкам во время выполнения, если вы не будете осторожны.
источник
Вот мой метод приведения объекта, но не к переменной общего типа, а к
System.Type
динамически:Я создаю лямбда-выражение во время выполнения, используя
System.Linq.Expressions
типFunc<object, object>
, который распаковывает входные данные, выполняет желаемое преобразование типов, а затем дает результат в штучной упаковке. Новый нужен не только для всех типов, которые подвергаются приведениям, но также и для типов, которые подвергаются приведению (из-за шага распаковки). Создание этих выражений отнимает много времени из-за рефлексии, компиляции и динамического построения метода, который делается под капотом. К счастью, после создания выражения можно вызывать многократно и без больших накладных расходов, поэтому я кеширую каждое из них.Обратите внимание, что это не волшебство. Приведение не происходит в коде, как это происходит с
dynamic
ключевым словом, конвертируются только базовые данные объекта. Во время компиляции нам все еще приходится тщательно выяснять, какого типа может быть наш объект, что делает это решение непрактичным. Я написал это как хак для вызова операторов преобразования, определенных произвольными типами, но, возможно, кто-нибудь найдет лучший вариант использования.источник
using System.Linq.Expressions;
Type t = typeof(MyGeneric<>).MakeGenericType(obj.OutputType); var a = (t)Convert.ChangeType(obj, t); var b = (t)Caster.Cast(t, obj);
Type
. Вы не можете использовать обычный синтаксис приведения, если все, что у вас есть, это объект Type. Если вы хотите иметь возможность использовать объект в качестве некоторого типа T во время компиляции, а не во время выполнения, вам нужно привести его с помощью переменной типа или просто фактического имени типа. Вы можете сделать первое, используя ответ Zaphrax.Если оставить в стороне упаковку и распаковку для простоты, то нет никакого конкретного действия во время выполнения, связанного с приведением в иерархию наследования. В основном это время компиляции. По сути, приведение говорит компилятору обрабатывать значение переменной как другой тип.
Что вы могли бы сделать после актерского состава? Вы не знаете тип, поэтому вы не сможете вызывать какие-либо методы для него. Там не было бы ничего особенного, что вы могли бы сделать. В частности, это может быть полезно, только если вы знаете возможные типы во время компиляции, приводите его вручную и обрабатывает каждый случай отдельно с помощью
if
операторов:источник
Как ты мог это сделать? Вам нужна переменная или поле типа T, где вы можете хранить объект после приведения, но как вы можете иметь такую переменную или поле, если вы знаете T только во время выполнения? Так что нет, это невозможно.
источник
CastTo
методObject
?Когда дело доходит до приведения к типу Enum:
И ты назовешь это так:
Это было важно для меня в случае получения значения атрибута Description нескольких типов перечисления по значению int:
а потом:
В качестве альтернативы (лучший подход) такое приведение может выглядеть так:
источник
После того, как я не нашел ничего, что можно обойти, исключение «Объект должен реализовывать IConvertible» при использовании ответа Zyphrax (кроме реализации интерфейса). Я попробовал что-то немного необычное и сработало для моей ситуации.
Используя пакет Nugets Newtonsoft.Json ...
источник
Вред, проблема в том, что у тебя нет T.
у вас есть только переменная типа.
Подсказка для MS, если бы вы могли сделать что-то вроде
TryCast<typeof(MyClass)>
если бы решить все наши проблемы.
источник
Я никогда не пойму, почему вам нужно до 50 репутации, чтобы оставить комментарий, но я просто должен был сказать, что ответ @Curt - это именно то, что я искал, и, надеюсь, кто-то еще.
В моем примере у меня есть атрибут ActionFilterAttribute, который я использовал для обновления значений документа json patch. Я не знал, что такое модель T для патч-документа, поэтому мне пришлось сериализовать и десериализовать его в простой JsonPatchDocument, изменить его, а затем, потому что у меня был тип, снова сериализовать и десериализовать его обратно в тип.
источник
источник
даже чище:
источник
Если вам нужно приводить объекты во время выполнения, не зная типа назначения, вы можете использовать отражение для создания динамического преобразователя.
Это упрощенная версия (без кеширования сгенерированного метода):
тогда вы можете назвать это:
источник