Подтвердить что ты не робот

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

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

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

MyClass abc = new MyClass();

Затем я могу сказать:

System.Type type = abc.GetType();

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

string className = "MyClass";
4b9b3361

Ответ 1

Это зависит от того, какая сборка является классом. Если в 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", вам нужно каким-то образом получить имя пространства имен (или имя пространства имен и имя сборки в случае, если это ссылка), и concat, что вместе с именем класса. Что-то вроде:

//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 и т.д.

Ответ 2

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

MSDN. Убедитесь, что имя Assembly Qualified.

Ответ 3

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

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]);

Ответ 4

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

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

Ответ 5

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

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


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;
}

Ответ 6

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

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

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

Ответ 7

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

    //  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;