En C #, puis-je convertir une variable de type objet en une variable de type T où T est défini dans une variable Type?
c#
reflection
types
theringostarrs
la source
la source
Type
variable, vous pouvez utiliser la réflexion pour créer une instance de ce type. Et puis, vous pouvez utiliser une méthode générique pour renvoyer le type souhaité en le déduisant d'un paramètre de ce type. Malheureusement, toute méthode de réflexion qui crée une instance d'un type aura un type de retour deobject
, donc votreCastByExample
méthode générique sera également utiliséeobject
. Il n'y a donc vraiment aucun moyen de le faire, et même s'il y en avait, que feriez-vous avec l'objet nouvellement casté? Vous ne pouvez pas utiliser ses méthodes ou quoi que ce soit parce que vous ne connaissez pas son type.object
oudynamic
. Si vous souhaitez charger dynamiquement des modules externes, vous pouvez demander aux classes de partager une interface commune et de convertir l'objet en cela. Si vous ne contrôlez pas le code tiers, créez de petits wrappers et implémentez l'interface à ce sujet.Réponses:
Voici un exemple de conversion et de conversion:
Éditer:
Certaines personnes dans les commentaires disent que cette réponse ne répond pas à la question. Mais la ligne
(T) Convert.ChangeType(input, typeof(T))
offre la solution. LaConvert.ChangeType
méthode essaie de convertir n'importe quel objet au type fourni comme deuxième argument.Par exemple:
J'ai écrit la réponse avec les génériques, parce que je pense qu'il est un signe très probable de l' odeur de code quand vous voulez lancer
a something
àa something else
sans traitement d' un type réel. Avec des interfaces appropriées qui ne devraient pas être nécessaires dans 99,9% des cas. Il y a peut-être quelques cas marginaux quand il s'agit de penser que cela pourrait avoir du sens, mais je recommanderais d'éviter ces cas.Modifier 2:
Quelques conseils supplémentaires:
object
oudynamic
.la source
T
tant que telle.Convert.ChangeType(input, typeof(T));
donne essentiellement la solution. Vous pouvez facilement le remplacertypeof(T)
par une variable de type existante. Une meilleure solution (si possible) serait d'empêcher le type dynamique tous ensemble.T
auquel il n'est pas disponible.T
mais vous n'obtenez toujours qu'unobject
comme référence. hmm, j'ai trouvé la question intéressante dans la prémisse que OP n'a que laType
variable et pas d'autres informations. Comme si la signature de la méthode étaitConvert(object source, Type destination)
:) Néanmoins, je reçois votre pointD'autres réponses ne mentionnent pas le type "dynamique". Donc, pour ajouter une réponse de plus, vous pouvez utiliser le type "dynamique" pour stocker votre objet résultant sans avoir à transtyper l'objet converti avec un type statique.
Gardez à l'esprit qu'avec l'utilisation de "dynamique" le compilateur contourne la vérification de type statique qui pourrait introduire des erreurs d'exécution possibles si vous ne faites pas attention.
la source
Voici ma méthode pour convertir un objet mais pas en une variable de type générique, plutôt en une
System.Type
dynamique:Je crée une expression lambda au moment de l'exécution en utilisant
System.Linq.Expressions
, de typeFunc<object, object>
, qui déballe son entrée, effectue la conversion de type souhaitée puis donne le résultat encadré. Un nouveau est nécessaire non seulement pour tous les types qui sont castés, mais aussi pour les types qui sont castés (en raison de l'étape de déballage). La création de ces expressions prend beaucoup de temps, en raison de la réflexion, de la compilation et de la construction de méthode dynamique qui se fait sous le capot. Heureusement, une fois créées, les expressions peuvent être invoquées à plusieurs reprises et sans surcharge, donc je mets chacune en cache.Notez que ce n'est pas magique. La conversion ne se produit pas dans le code, comme c'est le cas avec le
dynamic
mot clé, seules les données sous-jacentes de l'objet sont converties. Au moment de la compilation, il nous reste à déterminer minutieusement exactement quel type notre objet pourrait être, ce qui rend cette solution impraticable. J'ai écrit cela comme un hack pour invoquer des opérateurs de conversion définis par des types arbitraires, mais peut-être que quelqu'un peut trouver un meilleur cas d'utilisation.la source
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
. Vous ne pouvez pas transtyper en utilisant la syntaxe de transtypage normale si vous ne disposez que de l'objet Type. Si vous souhaitez pouvoir utiliser l'objet en tant que type T au moment de la compilation, et non à l'exécution, vous devez le convertir à l'aide d'une variable de type ou simplement du nom de type réel. Vous pouvez faire le premier en utilisant la réponse de Zaphrax.Mis à part la boxe et le déballage pour plus de simplicité, aucune action d'exécution spécifique n'est impliquée dans la coulée le long de la hiérarchie d'héritage. C'est surtout une question de temps de compilation. Essentiellement, un transtypage indique au compilateur de traiter la valeur de la variable comme un autre type.
Que pourriez-vous faire après le casting? Vous ne connaissez pas le type, vous ne pourrez donc pas appeler de méthode dessus. Il n'y aurait rien de spécial à faire. Plus précisément, il ne peut être utile que si vous connaissez les types possibles au moment de la compilation, convertissez-les manuellement et gérez chaque cas séparément avec des
if
instructions:la source
Comment pouvez vous faire ça? Vous avez besoin d'une variable ou d'un champ de type T où vous pouvez stocker l'objet après la conversion, mais comment pouvez-vous avoir une telle variable ou un champ si vous ne connaissez T qu'au moment de l'exécution? Donc, non, ce n'est pas possible.
la source
CastTo
méthodeObject
?En ce qui concerne le casting au type Enum:
Et vous l'appellerez comme ça:
Cela était essentiel pour moi en cas d'obtention de la valeur d'attribut Description de plusieurs types d'énumération par valeur int:
puis:
Alternativement (meilleure approche), un tel casting pourrait ressembler à ceci:
la source
Après n'avoir rien trouvé pour contourner l'exception "Object must implement IConvertible" lors de l'utilisation de la réponse de Zyphrax (sauf pour implémenter l'interface). J'ai essayé quelque chose d'un peu peu conventionnel et j'ai travaillé pour ma situation.
Utilisation du package de nuget Newtonsoft.Json ...
la source
Harm, le problème est que vous n'avez pas de T.
vous n'avez qu'une variable Type.
Astuce pour MS, si vous pouviez faire quelque chose comme
TryCast<typeof(MyClass)>
si résoudrait tous nos problèmes.
la source
Je ne comprendrai jamais pourquoi vous avez besoin de jusqu'à 50 points de réputation pour laisser un commentaire, mais je viens de dire que la réponse @Curt est exactement ce que je cherchais et j'espère que quelqu'un d'autre.
Dans mon exemple, j'ai un ActionFilterAttribute que j'utilisais pour mettre à jour les valeurs d'un correctif json. Je ne savais pas ce qu'était le modèle T pour le document de correction.J'ai dû le sérialiser et le désérialiser en un simple JsonPatchDocument, le modifier, puis parce que j'avais le type, le sérialiser et le désérialiser à nouveau vers le type.
la source
la source
encore plus propre:
la source
Si vous devez convertir des objets à l'exécution sans connaître le type de destination, vous pouvez utiliser la réflexion pour créer un convertisseur dynamique.
Il s'agit d'une version simplifiée (sans mise en cache de la méthode générée):
alors vous pouvez l'appeler:
la source