2009-12-16 4 views
0

je veux faire quelque chose comme ça:typeof ou Type.GetType pour un nom de type non qualifié

Type t=typeof(int?); 

ou

Type t=typeof(MemoryStream); 

Cependant, le paramètre est une chaîne ("? Int", » MemoryStream ", etc) et il n'est pas dans le nom du type qualifié assembly donc Type.GetType (string) ne fonctionnera pas. La raison pour laquelle je dois obtenir le type est parce que je fais une application simple de générateur de code et qu'il faut gérer la valeur de manière différente, et aussi si le type est Enumerable, il va itérer et faire une opération spécifique.

Avez-vous la bonne réponse?

Répondre

1

Eh bien, vous pourrait créer un compilateur-on-the-fly, comme ceci:

string getTypeHack = @"using System; public static class TypeHacker {{ public static Type GetThisType() {{ return typeof({0}); }} }}"; 

CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp"); 
CompilerParameters parameters = new CompilerParameters(); 
parameters.GenerateInMemory = true; 
parameters.GenerateExecutable = false; 
CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, string.Format(getTypeHack, "int")); 

Type hacker = results.CompiledAssembly.GetType("TypeHacker"); 
MethodInfo hack = hacker.GetMethod("GetThisType"); 
Type actualType = (Type)hack.Invoke(null, null); 

... mais cela est probablement une très mauvaise idée. Vous avez besoin d'un nouvel assemblage en mémoire pour chaque type que vous testez. Quelques problèmes au-dessus de ma tête:

  • Vous allez avoir memory-leakage-city avec le code ci-dessus; vous auriez besoin d'atténuer cela.
  • Ça va être lent.
  • C'est moche.
  • Vous pouvez toujours avoir des problèmes de résolution d'assembly, selon les types que vous autorisez.

(je pourrais effectivement me downvote pour cette suggestion ...): ^)

Est-il possible de factoriser l'application de passer d'un type? Cela va rendre votre vie tellement plus facile.

+0

Wow, merci! Ça marche! Je pense que je vais mettre en cache le résultat si j'utilise votre solution –

+0

OK, il suffit de regarder votre mémoire. Mettez en cache ce que vous pouvez, disposez tout ce qui est disponible dès que possible et créez des tables de recherche pour les fruits faciles comme "int", "chaîne", etc. Si vous pensez à un chemin à parcourir pour refactoriser, ou inclure des assemblages comme Jon mentionné, ça va être mieux. –

1

La raison typeof est en mesure de faire face à cela est que le compilateur connaît les raccourcis intégrés syntaxiques C# (int pour System.Int32, X? pour Nullable<X> etc) et regarder à travers les directives à l'aide, et il sait quels assemblages regarder.

Si vous voulez être capable de gérer tout ce que le compilateur C# peut gérer, vous aurez besoin de cette information vous-même. (Je suppose que vous n'aurez pas besoin d'alias d'espaces de noms, etc ...)

Pouvez-vous lui fournir une liste d'assemblys et une liste d'espaces de noms à vérifier?

+0

J'ai fait quelque chose comme itérer à travers AppDomain.CurrentDomain.GetAssemblies() et faire l'assemblage.GetType mais cela ne fonctionne toujours pas –

0

Vous pouvez énumérer tous les types à l'aide AppDomain.CurrentDomain.GetAssemblies(). SelectMany (a => a.GetExportedTypes())

Pour chaque type, vous pouvez comparer son nom à votre nom.

Cela fonctionne bien si vous ne l'utilisez pas trop car la performance n'est pas très bonne. Vous pourriez l'améliorer en créant un dictionnaire.

+0

Type.Name for int? Nullable'1 sera donc différent avec int? . Donc, je ne peux pas dépendre de la propriété Nom –

+0

Vous avez raison - les types génériques posent problème. Cela ne fonctionnerait qu'avec des types non génériques. – Matthias

Questions connexes