Способ встраивания / ссылки на другую сборку DLL при вызове метода с использованием C # Reflection

Есть ли способ вызвать методы с использованием C # Reflection со встроенными / ссылочными dll?

Например, рассмотрим следующий сценарий. У меня есть вызов сборки User.dll, класс которого указан ниже

namespace User
{
    public class UserInfo
    {
        public static string Name = "Username";
    }
}

Используя указанную выше dll в качестве ссылки, я могу скомпилировать следующий код и получить доступ к переменной UserInfo.Name.

using User;
using System.Windows.Forms;

public class Test
{
    public Test()
    {
        MessageBox.Show("Name : " + UserInfo.Name);
    }
}

Учтите, что приведенный выше код находится в другой сборке DLL с именем Test.dll. Используя Assembly.LoadFile ("Test.dll") и C # Reflection, когда я пытаюсь вызвать конструктор, получаю ошибку выполнения "Файл не найден".

Ошибка

System.Reflection.TargetInvocationException: исключение было выброшено целью вызова. ---> System.IO.FileNotFoundException: не удалось загрузить файл или сборку DynamicAssembly, Version = 0.0.0.0, Culture = нейтральный, PublicKeyToken = null или одну из их зависимостей. Система не может найти указанный файл. в Test..ctor () --- Конец трассировки стека внутреннего исключения --- в System.RuntimeMethodHandle.InvokeMethod (цель объекта, аргументы Object [], сигнатуры, логический конструктор) в System.Reflection.RuntimeConstructorInfo.Invoke (BindingFlags invokeAttr, Binder binder, параметры Object [], культура CultureInfo) в System.Reflection.ConstructorInfo.Invoke (параметры Object [])


person Ramanan    schedule 13.12.2017    source источник


Ответы (2)


Метод Assembly.LoadFile загружает только указанный файл. В вашем случае вам нужно использовать метод Assembly.LoadFrom. Проверьте различия между Assembly.LoadFile и Assembly.LoadFrom

LoadFrom () проходит через Fusion и может быть перенаправлен на другую сборку по другому пути, но с тем же идентификатором, если он уже загружен в контекст LoadFrom.

LoadFile () вообще не связывается через Fusion - загрузчик просто выполняет * и загружает именно то, что запросил вызывающий. Он не использует контексты Load или LoadFrom.

Ваш пример исполняемого кода будет похож на

    static void Main(string[] args)
    {
        var fileName = ""; //put here test.dll path
        Assembly ass = Assembly.LoadFrom(fileName);

        var type = ass.GetType("Test.Test"); 

        var test = Activator.CreateInstance(type);
    }
person Mutlu Kaya    schedule 13.12.2017
comment
Спасибо @nmkaya. Я тоже пробовал с методом LoadFrom. Но проблема в том, что если ссылающаяся сборка (User.dll) находится на другом пути, она не вызывает метод и не получает такое же исключение FileNotFound. Таким образом, единственный обходной путь обнаружил, что программно копируйте или перемещайте ссылочные сборки (например, User.dll) в каталог исполняемого приложения перед вызовом метода. (например, Debug \ bin). - person Ramanan; 19.12.2017
comment
@ ramanan.java, User.dll должен находиться в расположении Test.dll или Gac, иначе Test.dll не будет работать, даже если он добавлен в качестве ссылки на проект (в этом случае сборки тестового проекта также копируются в расположение основного приложения). Вам не нужно копировать Test.dll и User.dll, если User.dll можно получить из расположения Test.dll. Обратите внимание, что я проверил, как это работает с тестовым приложением, и думаю, может быть, в вашей ситуации есть еще одна проблема, например. Основное приложение не может загрузить User.dll, потому что оно заблокировано другим процессом. - person Mutlu Kaya; 19.12.2017

У меня такая же проблема.

Я просто скопировал DLL в папку bin проекта.

person Tushar Borchate    schedule 26.07.2019