Получение System.Type из частичного имени типа

Я хочу получить System.Type с учетом только имени типа в string.

Например, если у меня есть объект:

MyClass abc = new MyClass();

Тогда я могу сказать:

System.Type type = abc.GetType();

Но что, если все, что у меня есть, это:

string className = "MyClass";

person Mark T    schedule 07.10.2008    source источник
comment
возможный дубликат Избегайте указания имени пространства имен в Type.GetType ()   -  person Fr33dan    schedule 18.08.2014
comment
@ Fr33dan, круговая петля? В упомянутом возможном оригинале упоминается этот вопрос как возможный исходный (см. комментарий)? :)   -  person publicgk    schedule 11.12.2014
comment
@publicgk Я на самом деле пытался пометить его для слияния с этим вопросом, поскольку они одинаковы, но на этот вопрос, и у обоих есть хорошие ответы. См. этот мета-вопрос. Очевидно, я сделал это неправильно и сдался, потом кто-то пришел позже и решил, что это дубликат, поскольку другой был более старым вопросом.   -  person Fr33dan    schedule 11.12.2014


Ответы (7)


Это зависит от того, в какой сборке находится класс. Если он находится в mscorlib или вызывающей сборке, все, что вам нужно, это

Type type = Type.GetType("namespace.class");

Но если на него есть ссылка из какой-то другой сборки, вам нужно будет сделать:

Assembly assembly = typeof(SomeKnownTypeInAssembly).Assembly;
Type type = assembly.GetType("namespace.class");

//or

Type type = Type.GetType("namespace.class, assembly");

Если у вас есть только имя класса «MyClass», вам нужно каким-то образом получить имя пространства имен (или имя пространства имен и имя сборки, если это сборка, на которую имеется ссылка) и объединить его вместе с именем класса. Что-то типа:

//if class is in same assembly
var namespace = typeof(SomeKnownTypeInNamespace).Namespace;
Type type = Type.GetType(namespace + "." + "MyClass");


//or for cases of referenced classes
var assembly = typeof(SomeKnownTypeInAssembly).Assembly;
var namespace = typeof(SomeKnownTypeInNamespace).Namespace;
Type type = assembly.GetType(namespace + "." + "MyClass");
//or
Type type = Type.GetType(namespace + "." + "MyClass" + ", " + assembly.GetName().Name);

Если у вас нет абсолютно ничего (не известно даже имени сборки или имени пространства имен), кроме только имени класса, вы можете запросить все сборки, чтобы выбрать соответствующую строку. Но это должно быть намного медленнее:

Type type = AppDomain.CurrentDomain.GetAssemblies()
                                   .SelectMany(x => x.GetTypes())
                                   .FirstOrDefault(x => x.Name == "MyClass");

Обратите внимание, что это возвращает первый соответствующий класс, поэтому нет необходимости быть очень точным, если у вас будет несколько классов с одинаковым именем в сборках / пространствах имен. В любом случае кеширование значений здесь имеет смысл. Чуть более быстрый способ - предположить, что существует одно пространство имен по умолчанию:

Type type = AppDomain.CurrentDomain.GetAssemblies()
                                   .Select(a => new { a, a.GetTypes().First().Namespace })
                                   .Select(x => x.a.GetType(x.Namespace + "." + "MyClass"))
                                   .FirstOrDefault(x => x != null);

Но это снова предположение, что ваш тип будет иметь то же пространство имен, что и какой-то другой случайный класс в сборке; слишком хрупкий, не очень хорошо.


Если вам нужны классы других доменов, вы можете получить список всех доменов приложений, перейдя по этой ссылке. Затем вы можете выполнить те же запросы, что и для каждого домена, как показано выше. Если ваша сборка, в которой находится тип, еще не загружена, вам придется вручную загрузить ее, используя Assembly.Load, Assembly.LoadFrom и т. Д.

person nawfal    schedule 05.12.2013
comment
Обратите внимание, что поиск типа только по имени во всех загруженных сборках может открыть брешь в безопасности в вашем приложении - если злонамеренный субъект сможет ввести сборку, содержащую класс с тем же именем и иерархией наследования, что и у вас. повторный поиск. - person Ian Kemp; 28.06.2019

Type type = Type.GetType("foo.bar.MyClass, foo.bar");

MSDN. Убедитесь, что указано имя Assembly Qualified.

person Chris Marasti-Georg    schedule 07.10.2008
comment
Важное примечание: требуется полное имя типа. - person leppie; 07.10.2008

Чтобы создать экземпляр вашего класса после того, как вы получите тип и вызовете метод -

Type type = Type.GetType("foo.bar.MyClass, foo.bar");
object instanceObject = System.Reflection.Activator.CreateInstance(type);
type.InvokeMember(method, BindingFlags.InvokeMethod, null, instanceObject, new object[0]);
person Seibar    schedule 07.10.2008

Type type = Type.GetType("MyClass");

Обязательно укажите пространство имен. Существуют перегрузки метода, которые управляют чувствительностью к регистру и тем, возникает ли исключение, если имя типа не найдено.

person jalbert    schedule 07.10.2008
comment
Из документации: если тип находится в выполняющейся в данный момент сборке или в Mscorlib.dll, достаточно указать имя типа, определяемое его пространством имен. - person jalbert; 07.10.2008
comment
Тип находится в выполняющейся в данный момент сборке? ОП не уточнил. - person Chris Marasti-Georg; 07.10.2008

Другой способ получить тип из текущей или другой сборки.

(Предполагается, что пространство имен класса содержит его сборку):


public static Type GetType(string fullName)
{
    if (string.IsNullOrEmpty(fullName))
        return null;
    Type type = Type.GetType(fullName);
    if (type == null)
    {
        string targetAssembly = fullName;
        while (type == null && targetAssembly.Length > 0)
        {
            try
            {
                int dotInd = targetAssembly.LastIndexOf('.');
                targetAssembly = dotInd >= 0 ? targetAssembly.Substring(0, dotInd) : "";
                if (targetAssembly.Length > 0)
                    type = Type.GetType(fullName + ", " + targetAssembly);
            }
            catch { }
        }
    }
    return type;
}
person Chris W    schedule 31.01.2013

Вот простой метод создания и инициализации нового объекта на основе его имени и параметров:

    //  Creates and initializes a new object from its name and parameters
    public Object CreateObjectByName(string name, params Object[] args)
    {
        string s = "<prefix>" + name;    // case sensitive; Type.FullName
        Type type = Type.GetType(s);
        Object o = System.Activator.CreateInstance(type, args);
        return o;
    }

Одним из примеров того, как это можно использовать, является чтение файла, содержащего имена классов [или частичные имена классов] и параметры, а затем добавление возвращаемых объектов в список объектов базового типа, общего для созданных объектов.

Чтобы увидеть, как должно выглядеть имя вашего класса [или], временно используйте что-то вроде этого [если ваш класс называется NewClass]:

    string z = (new NewClass(args)).GetType().FullName;
person shadow    schedule 25.09.2013

Type.GetType(...) иногда может выйти из строя, если оператор typeof не может быть использован.

Вместо этого вы можете подумать о сборках из текущего домена, чтобы сделать это.

проверьте мой ответ в этой теме

person dmihailescu    schedule 02.09.2011