Преобразовать имя "C# friendly type" в фактический тип: "int" = > typeof(int)
Я хочу получить System.Type дали string это указывает (примитивный) тип в C# имя в принципе, как компилятор C# делает при чтении исходного кода C#.
Я чувствую, что лучший способ описать то, что мне нужно,-это юнит-тест.
Я надеюсь, что существует общая техника, которая может сделать все приведенные ниже утверждения проходными, а не пытаться жестко кодировать специальные случаи для специального C# имена.
Type GetFriendlyType(string typeName){ ...??... }
void Test(){
    // using fluent assertions
    GetFriendlyType( "bool" ).Should().Be( typeof(bool) );
    GetFriendlyType( "int" ).Should().Be( typeof(int) );
    // ok, technically not a primitive type... (rolls eyes)
    GetFriendlyType( "string" ).Should().Be( typeof(string) ); 
    // fine, I give up!
    // I want all C# type-aliases to work, not just for primitives
    GetFriendlyType( "void" ).Should().Be( typeof(void) );
    GetFriendlyType( "decimal" ).Should().Be( typeof(decimal) ); 
    //Bonus points: get type of fully-specified CLR types
    GetFriendlyName( "System.Activator" ).Should().Be(typeof(System.Activator));
    //Hi, Eric Lippert! 
    // Not Eric? https://stackoverflow.com/a/4369889/11545
    GetFriendlyName( "int[]" ).Should().Be( typeof(int[]) ); 
    GetFriendlyName( "int[,]" ).Should().Be( typeof(int[,]) ); 
    //beating a dead horse
    GetFriendlyName( "int[,][,][][,][][]" ).Should().Be( typeof(int[,][,][][,][][]) ); 
}
что я пробовал до сих пор:
этот вопрос является дополнением мой старый вопрос спрашивает, Как получить "дружественное имя" от типа.
ответ на этот вопрос: используйте CSharpCodeProvider
using (var provider = new CSharpCodeProvider())
{
    var typeRef = new CodeTypeReference(typeof(int));
    string friendlyName = provider.GetTypeOutput(typeRef);
}
Я не могу понять, как (или если возможно) сделать наоборот и получить фактический тип C# от CodeTypeReference (он также имеет ctor, который принимает string)
var typeRef = new CodeTypeReference(typeof(int));
            5 ответов
вот способ сделать это с помощью Рослин:
using System;
using System.Linq;
using Roslyn.Scripting.CSharp;
namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(GetType("int[,][,][][,][][]"));
            Console.WriteLine(GetType("Activator"));
            Console.WriteLine(GetType("List<int[,][,][][,][][]>"));
        }
        private static Type GetType(string type)
        {
            var engine = new ScriptEngine();
            new[] { "System" }
                .ToList().ForEach(r => engine.AddReference(r));
            new[] { "System", "System.Collections.Generic" }
                .ToList().ForEach(ns => engine.ImportNamespace(ns));
            return engine
                .CreateSession()
                .Execute<Type>("typeof(" + type + ")");
        }
    }
}
разве у вас нет большей части if, уже разработанной?
следующее дает вам все встроенные типы C# согласно http://msdn.microsoft.com/en-us/library/ya5y69ds.aspx, плюс void.
using Microsoft.CSharp;
using System;
using System.CodeDom;
using System.Reflection;
namespace CSTypeNames
{
    class Program
    {
        static void Main(string[] args)
        {
            // Resolve reference to mscorlib.
            // int is an arbitrarily chosen type in mscorlib
            var mscorlib = Assembly.GetAssembly(typeof(int));
            using (var provider = new CSharpCodeProvider())
            {
                foreach (var type in mscorlib.DefinedTypes)
                {
                    if (string.Equals(type.Namespace, "System"))
                    {
                        var typeRef = new CodeTypeReference(type);
                        var csTypeName = provider.GetTypeOutput(typeRef);
                        // Ignore qualified types.
                        if (csTypeName.IndexOf('.') == -1)
                        {
                            Console.WriteLine(csTypeName + " : " + type.FullName);
                        }
                    }
                }
            }
            Console.ReadLine();
        }
    }
}
это основано на нескольких предположениях, которые я считаю правильными на момент написания:
- все встроенные типы C# являются частью mscorlib.файл DLL.
 - все встроенные типы C# являются псевдонимами типов, определенных в 
Systemпространство имен. - 
только имена встроенных типов C#, возвращаемые вызовом 
CSharpCodeProvider.GetTypeOutputнет ни одного ".' в них. 
выход:
object : System.Object
string : System.String
bool : System.Boolean
byte : System.Byte
char : System.Char
decimal : System.Decimal
double : System.Double
short : System.Int16
int : System.Int32
long : System.Int64
sbyte : System.SByte
float : System.Single
ushort : System.UInt16
uint : System.UInt32
ulong : System.UInt64
void : System.Void
теперь я просто должен сидеть и ждать, пока Эрик придет и скажет мне просто как ошибся я. Я смирился со своей судьбой.
псевдонимы, такие как "int", "bool" и т. д. не являются частью .NET Framework. Внутренне они преобразуются в систему.Int32, System.Логическое и т. д. Тип.GetType ("int") должен вернуть вам значение null. Лучший способ appoach это, имея словарь для сопоставления псевдонимов с их типом, например
        Dictionary<string, Type> PrimitiveTypes = new Dictionary<string, Type>();
        PrimitiveTypes.Add("int", typeof(int));
        PrimitiveTypes.Add("long", typeof(long));
        etc.etc..
вот один из способов сделать это:
public Type GetType(string friendlyName)
{
    var provider = new CSharpCodeProvider();
    var pars = new CompilerParameters
    {
        GenerateExecutable = false,
        GenerateInMemory = true
    };
    string code = "public class TypeFullNameGetter"
                + "{"
                + "     public override string ToString()"
                + "     {"
                + "         return typeof(" + friendlyName + ").FullName;"
                + "     }"
                + "}";
    var comp = provider.CompileAssemblyFromSource(pars, new[] { code });
    if (comp.Errors.Count > 0)
        return null;
    object fullNameGetter = comp.CompiledAssembly.CreateInstance("TypeFullNameGetter");
    string fullName = fullNameGetter.ToString();            
    return Type.GetType(fullName);
}
затем, если вы передадите "int", "int []" и т. д., Вы получите соответствующий тип обратно.
вот мой удар по нему. Я подошел к нему, используя две похожие библиотеки:
- Mono C# compiler-as-a-service
 - компилятор MS Roslyn C#
 
Я думаю, что это довольно чистый и простой.
здесь я использую компилятор-как-услугу C# Mono, а именно Mono.CSharp.Evaluator класса. (Он доступен как пакет Nuget имени, неудивительно, моно.Используется CSharp)
using Mono.CSharp;
    public static Type GetFriendlyType(string typeName)
    {
        //this class could use a default ctor with default sensible settings...
        var eval = new Mono.CSharp.Evaluator(new CompilerContext(
                                                 new CompilerSettings(),
                                                 new ConsoleReportPrinter()));
        //MAGIC! 
        object type = eval.Evaluate(string.Format("typeof({0});", typeName));
        return (Type)type;
    }
далее: Двойник из "друзья в здании 41" Рослин "ака"...
позже:
Roslyn почти так же легко установить-как только вы поймете, что к чему. В итоге я использовал Nuget пакет " Рослин.Компиляторы.Используется CSharp" (или получить его как VS add-in). Просто предупреждаю, что Рослин требует а .Проект Net 4.5.
код еще чище:
using Roslyn.Scripting.CSharp;
    public static Type GetFriendlyType(string typeName)
    {
        ScriptEngine engine = new ScriptEngine();
        var type = engine.CreateSession()
                         .Execute<Type>(string.Format("typeof({0})", typeName));
        return type;
    }