Получение System.Type из частичного имени типа - PullRequest
36 голосов
/ 07 октября 2008

Я хочу получить System.Type, учитывая только имя типа в string.

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

MyClass abc = new MyClass();

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

System.Type type = abc.GetType();

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

string className = "MyClass";

Ответы [ 7 ]

39 голосов
/ 05 декабря 2013

Зависит от того, какой сборкой является класс. Если он находится в 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 и т. Д.

33 голосов
/ 07 октября 2008
2 голосов
/ 07 октября 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]);
1 голос
/ 31 января 2013

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

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


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;
}
1 голос
/ 07 октября 2008
Type type = Type.GetType("MyClass");

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

0 голосов
/ 25 сентября 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;
0 голосов
/ 02 сентября 2011

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

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

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

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