Могу ли я загрузить сборку .NET во время выполнения и создать экземпляр типа, зная только имя? - PullRequest
171 голосов
/ 21 января 2009

Можно ли создать экземпляр объекта во время выполнения, если у меня есть только имя DLL и имя класса, без добавления ссылки на сборку в проекте? Класс реализует интерфейс, поэтому, как только я создам экземпляр класса, я приведу его к интерфейсу.

Название сборки:

library.dll

Имя типа:

Company.Project.Classname


РЕДАКТИРОВАТЬ: У меня нет абсолютного пути к DLL, поэтому Assembly.LoadFile не будет работать. DLL может находиться в корне приложения, system32 или даже загружаться в GAC.

Ответы [ 13 ]

215 голосов
/ 21 января 2009

Да. Вам нужно использовать Assembly.LoadFrom для загрузки сборки в память, затем вы можете использовать Activator.CreateInstance для создания экземпляра предпочитаемого вами типа. Сначала вам нужно будет найти тип с помощью отражения. Вот простой пример:

Assembly assembly = Assembly.LoadFrom("MyNice.dll");

Type type = assembly.GetType("MyType");

object instanceOfMyType = Activator.CreateInstance(type);

Обновление

Если у вас есть имя файла сборки и имя типа, вы можете использовать Activator.CreateInstance(assemblyName, typeName), чтобы запросить разрешение типа .NET, чтобы преобразовать его в тип. Вы можете обернуть это с помощью try / catch, чтобы в случае неудачи вы могли выполнить поиск по каталогам, где вы можете специально хранить дополнительные сборки, которые иначе не могли бы быть найдены. Это будет использовать предыдущий метод в этой точке.

34 голосов
/ 21 января 2009

Рассмотрим ограничения различных методов Load*. Из MSDN документов ...

LoadFile не загружает файлы в контекст LoadFrom, а не разрешает зависимости с использованием пути загрузки, как метод LoadFrom.

Дополнительную информацию о контекстах загрузки можно найти в LoadFrom документах.

18 голосов
/ 21 января 2009

Activator.CreateInstance должно работать.

IFace object = (IFace)Activator.CreateInstance( "AssemblyName",
                                                "TypeName" )
                               .Unwrap();

Примечание: Имя типа должно быть полностью квалифицированным.

Пример:

var aray = (IList)Activator.CreateInstance("mscorlib","System.Collections.ArrayList").Unwrap();
aray.Add(10);

foreach (object obj in aray)
{
    Console.WriteLine(obj);
}
6 голосов
/ 17 февраля 2012

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

Первое решение:

string assemblyName = "library.dll";
string assemblyPath = HttpContext.Current.Server.MapPath("~/bin/" + assemblyName);
Assembly assembly = Assembly.LoadFrom(assemblyPath);
Type T = assembly.GetType("Company.Project.Classname");
Company.Project.Classname instance = (Company.Project.Classname) Activator.CreateInstance(T);

Второй раствор

string assemblyName = "library.dll";
string assemblyPath = HttpContext.Current.Server.MapPath("~/bin/" + assemblyName);
Assembly assembly = Assembly.LoadFile(assemblyPath);
(Company.Project.Classname) instance = (Company.Project.Classname) assembly.CreateInstance("Company.Project.Classname");

Вы можете использовать тот же принцип для интерфейсов (вы будете создавать класс, но приведение к интерфейсу), например:

(Company.Project.Interfacename) instance = (Company.Project.Interfacename) assembly.CreateInstance("Company.Project.Classname");

Этот пример относится к веб-приложению, но подобное можно использовать и для настольных приложений, иначе разрешается только путь, например

Path.GetDirectoryName(Application.ExecutablePath)
3 голосов
/ 27 февраля 2017

Начиная с Framework v4.5, вы можете использовать Activator.CreateInstanceFrom () для простого создания экземпляров классов в сборках. В следующем примере показано, как его использовать и как вызывать метод, передавая параметры и получая возвращаемое значение.

    // Assuming moduleFileName contains full or valid relative path to assembly    
    var moduleInstance = Activator.CreateInstanceFrom(moduleFileName, "MyNamespace.MyClass");
    MethodInfo mi = moduleInstance.Unwrap().GetType().GetMethod("MyMethod");
    // Assuming the method returns a boolean and accepts a single string parameter
    bool rc = Convert.ToBoolean(mi.Invoke(moduleInstance.Unwrap(), new object[] { "MyParamValue" } ));
3 голосов
/ 02 мая 2016

Это просто.

Пример из MSDN:

public static void Main()
{
    // Use the file name to load the assembly into the current
    // application domain.
    Assembly a = Assembly.Load("example");
    // Get the type to use.
    Type myType = a.GetType("Example");
    // Get the method to call.
    MethodInfo myMethod = myType.GetMethod("MethodA");
    // Create an instance.
    object obj = Activator.CreateInstance(myType);
    // Execute the method.
    myMethod.Invoke(obj, null);
}

Вот ссылка на ссылку

https://msdn.microsoft.com/en-us/library/25y1ya39.aspx

2 голосов
/ 12 января 2016
Assembly assembly = Assembly.LoadFrom("MyAssembly.dll");

Type type = assembly.GetType("MyType");

dynamic instanceOfMyType = Activator.CreateInstance(type);

Таким образом, таким образом вы можете использовать функции, не получая methodinfo, а затем вызывать его. Но вы не можете использовать Intellisense, потому что динамические типы вводятся во время выполнения, а не во время компиляции.

2 голосов
/ 21 января 2009

Вы можете загрузить сборку, используя методы * Assembly.Load **. Используя Activator.CreateInstance , вы можете создавать новые экземпляры нужного вам типа. Помните, что вам нужно использовать полное имя типа класса, который вы хотите загрузить (например, Namespace.SubNamespace.ClassName ). Используя метод InvokeMember класса Type , вы можете вызывать методы для типа.

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

2 голосов
/ 21 января 2009

В зависимости от того, насколько эта функциональность присуща вашему проекту, вы можете рассмотреть что-то вроде MEF , которое позаботится о загрузке и связывании компонентов для вас.

2 голосов
/ 21 января 2009
((ISomeInterface)Activator.CreateInstance(Assembly.LoadFile("somePath").GetTypes()[0])).SomeInterfaceMethod();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...