Как проверить, существует ли пространство имен, класс или метод в C #? - PullRequest
37 голосов
/ 14 декабря 2011

У меня есть программа на C #, как я могу проверить во время выполнения, существует ли пространство имен, класс или метод? Кроме того, как создать экземпляр класса, используя его имя в виде строки?

псевдокод:

string @namespace = "MyNameSpace";
string @class = "MyClass";
string method= "MyMEthod";

var y = IsNamespaceExists(namespace);
var x = IsClassExists(@class)? new @class : null; //Check if exists, instantiate if so.
var z = x.IsMethodExists(method);

Ответы [ 3 ]

42 голосов
/ 14 декабря 2011

Вы можете использовать Type.GetType (string) до отражает тип.GetType вернет ноль, если тип не найден.Если тип существует, вы можете использовать GetMethod, GetField, GetProperty и т. Д. Из возвращенного Type, чтобы проверить, существует ли интересующий вас элемент.

Обновите в соответствии с вашим примером:

string @namespace = "MyNameSpace";
string @class = "MyClass";
string method= "MyMEthod";

var myClassType = Type.GetType(String.format("{0}.{1}", @namespace, @class));
object instance = myClassType == null ? null : Activator.CreateInstance(myClassType); //Check if exists, instantiate if so.
var myMethodExists = myClassType.GetMethod(method) != null;

Console.WriteLine(myClassType); // MyNameSpace.MyClass
Console.WriteLine(myMethodExists); // True

Это наиболее эффективный и предпочтительный метод, при условии, что тип находится в выполняющейся в данный момент сборке , в mscorlib (не уверен, как .NET Core влияет на это, возможно, вместо этого System.Runtime?), или у вас есть имя для сборки для типа.Если строковый аргумент, который вы передаете GetType, не удовлетворяет этим трем требованиям, GetType вернет ноль (при условии, что нет другого типа, который случайно перекрывает эти требования, упс).


Если у вас нет квалифицированного имени сборки, вам нужно либо исправить свой подход, либо выполнить поиск, который может быть значительно медленнее.

Если мыПредположим, что вы хотите искать тип во всех загруженных сборках, вы можете сделать что-то вроде этого (используя LINQ):

var type = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
            from type in assembly.GetTypes()
            where type.Name == className
            select type);

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

Что касается определения пространств имен, отражение не экспортирует их отчетливо.Вместо этого вам нужно сделать что-то вроде:

var namespaceFound = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetTypes()
where type.Namespace == namespace
select type).Any()

Собрав все это вместе, вы получите что-то вроде:

var type = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                from type in assembly.GetTypes()
                where type.Name == className && type.GetMethods().Any(m => m.Name == methodName)
                select type).FirstOrDefault();

if (type == null) throw new InvalidOperationException("Valid type not found.");

object instance = Activator.CreateInstance(type);
33 голосов
/ 14 декабря 2011

Вы можете разрешить Тип из строки, используя метод Type.GetType (String) .Например:

Type myType = Type.GetType("MyNamespace.MyClass");

Вы можете использовать этот экземпляр типа, чтобы проверить, существует ли метод для типа, вызвав метод GetMethod (String) .Например:

MethodInfo myMethod = myType.GetMethod("MyMethod");

Как GetType, так и GetMethod возвращают null, если для данного имени не найден тип или метод, поэтому вы можете проверить, существует ли ваш тип / метод, проверив, возвращал ли ваш вызов метода нульили нет.

Наконец, вы можете создать экземпляр своего типа, используя Activator.CreateInstance (Тип) Например:

object instance = Activator.CreateInstance(myType);
2 голосов
/ 14 декабря 2011

Одно слово: Отражение . За исключением пространств имен, вам придется анализировать их по именам типов.

РЕДАКТИРОВАТЬ: Удивите это - для пространств имен вы должны будете использовать свойство Type.Namespace, чтобы определить, к какому пространству имен принадлежит каждый класс. (См. HackedByChinese ответ для получения дополнительной информации).

...