С# - Как проверить, существует ли в С# пространство имен, класс или метод?

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

псевдокод:

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

Ответ 1

Вы можете использовать Type.GetType(string) для отображения типа. GetType вернет 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 вернет значение null (при условии, что нет другого типа, который случайно перекрывает эти требования, упс).


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

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

Ответ 2

Вы можете разрешить Type из строки с помощью Метод Type.GetType(String). Например:

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

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

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

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

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

object instance = Activator.CreateInstance(myType);

Ответ 3

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

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