Создать и использовать экземпляр класса, имя которого известно только во время выполнения - PullRequest
4 голосов
/ 10 мая 2010

У меня есть список имен классов и методов, которые могут быть прочитаны только во время выполнения. Можно ли динамически создать такой класс? В настоящее время я использую C # 4.0.

Ответы [ 3 ]

3 голосов
/ 10 мая 2010

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

К счастью, оба возможны.

Второй сценарий более вероятен, поэтому вам следует взглянуть на рефлексию (ниже) - но учтите, что с этим связаны ограничения производительности (и такие мелкие вещи, как «какие аргументы принимает метод», становятся очень важными) .

Для первого сценария вам нужно взглянуть на TypeBuilder, но это намного более сложно. Другим вариантом будет CSharpCodeProvider и динамическая загрузка сборки, но опять-таки - нетривиально ни при каких условиях.

using System;
namespace MyNamespace {
    public class Foo {
        public void Bar() {
            Console.WriteLine("Foo.Bar called");
        }
    }
}
class Program {
    static void Main() {
        string className = "MyNamespace.Foo, MyAssemblyName",
            methodName = "Bar";
        Type type = Type.GetType(className);
        object obj = Activator.CreateInstance(type);
        type.GetMethod(methodName).Invoke(obj, null);
    }
}

Чтобы включить параметры (комментарии), вы передаете object[] вместо null:

using System;
namespace MyNamespace {
    public class Foo {
        public void Bar(string value) {
            Console.WriteLine("Foo.Bar called: " + value);
        }
    }
}
class Program {
    static void Main() {
        string className = "MyNamespace.Foo, MyAssemblyName",
            methodName = "Bar";
        Type type = Type.GetType(className);
        object obj = Activator.CreateInstance(type);
        object[] args = { "hello, world" };
        type.GetMethod(methodName).Invoke(obj, args);
    }
}

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

0 голосов
/ 10 мая 2010

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

Могу ли я создать экземпляр класса и вызвать его метод, в котором класс и метод указываются во время выполнения?

Конечно. Сначала простой путь. Используйте if операторы:

var className = "MyClass";
var methodName = "MyMethod";


if (className == typeof(MyClass).Name) {
  var instance = new MyClass();
  if (methodName == "MyMethod")
    instance.MyMethod();
  if (methodName == "MyOtherMethod")
    instance.MyOtherMethod();
}

Кроме того, вы можете использовать Activator.CreateInstance для создания экземпляра класса для вас.

var className = "MyClass";
var methodName = "MyMethod";

//Get a reference to the Assembly that has the desired class. Assume that all classes that we dynamically invoke are in the same assembly as MyClass.

var assembly = typeof(MyClass).Assembly;
//Find the type that we want to create
var type = assembly.GetTypes().FirstOrDefault(t=>t.Name == className);
if(type != null) {
  //Create an instance of this type.
  var instance = Activator.CreateInstance(type);
  //Find the method and call it.
  instance.GetType().GetMethod(methodName).Invoke(instance);
}

Можно ли создать класс во время выполнения?

Да, можно, но это сложно. Если вы опытный программист на C #, знаете немного о C ++ и ассемблере, вы сможете это сделать. Если нет, не беспокойтесь.

Microsoft предоставляет библиотеку для передачи кода на промежуточном языке, называемую Surpose, IL.Emit. Существует очень мало проблем, которые оправдывают использование этого метода, среди которых генерация фиктивных объектов и некоторые аспекты внедрения зависимостей. Вполне вероятно, что вашу проблему лучше решить другим способом.

0 голосов
/ 10 мая 2010

Для этого вы можете использовать функциональность IL emit прямо из .Net framework. Вам нужно будет изучить IL, чтобы динамически генерировать информацию о типе во время выполнения - это не для сердца.

Введение в создание динамических типов с помощью System.Reflection.Emit

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