Я хочу получить System.Type с учетом только имени типа в string.
Например, если у меня есть объект:
MyClass abc = new MyClass();
Тогда я могу сказать:
System.Type type = abc.GetType();
Но что, если все, что у меня есть, это:
string className = "MyClass";
@ Fr33dan, круговая петля? Упомянутый возможный оригинал упоминает этот вопрос как возможный оригинал (см. комментарий)? :)
@publicgk Я на самом деле пытался пометить его для слияния с этим вопросом, поскольку они одинаковы, но на этот вопрос, и у обоих есть хорошие ответы. См. этот мета вопрос. Очевидно, я сделал это неправильно и сдался, затем кто-то пришел позже и решил, что это дубликат, поскольку другой был более старым вопросом.





Type type = Type.GetType("foo.bar.MyClass, foo.bar");
MSDN. Убедитесь, что имя - Квалифицированная сборка.
Важное примечание: требуется полное имя типа.
Type type = Type.GetType("MyClass");
Обязательно укажите пространство имен. Существуют перегрузки метода, которые управляют чувствительностью к регистру и тем, возникает ли исключение, если имя типа не найдено.
Из документации: «Если тип находится в выполняющейся в данный момент сборке или в Mscorlib.dll, достаточно указать имя типа, определяемое его пространством имен».
Тип находится в выполняющейся в данный момент сборке? ОП не уточнил.
Чтобы создать экземпляр вашего класса после того, как вы получите тип и вызовете метод -
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]);
Type.GetType(...) может иногда выходить из строя, если оператор typeof не может быть использован.
Вместо этого вы можете подумать о сборках из текущего домена, чтобы сделать это.
проверьте мой ответ на эта ветка
Другой способ получить тип из текущей или другой сборки.
(Предполагается, что пространство имен класса содержит его сборку):
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;
}
Вот простой метод создания и инициализации нового объекта на основе его имени и параметров:
// 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;
Это зависит от того, в какой сборке находится класс. Если это 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 и т. д.
Обратите внимание, что поиск типа только по имени во всех загруженных сборках может открыть брешь в безопасности в вашем приложении - если злонамеренный субъект сможет ввести сборку, содержащую класс с тем же именем и иерархией наследования, что и у вас. повторный поиск.
возможный дубликат Избегайте указания имени пространства имен в Type.GetType ()