Подтвердить что ты не робот

Загрузка DLL файлов во время выполнения в С#

Я пытаюсь выяснить, как вы можете импортировать и использовать DLL во время выполнения внутри приложения С#. С помощью Assembly.LoadFile() мне удалось загрузить мою программу для загрузки dll (эта часть определенно работает, поскольку я могу получить имя класса с ToString()), однако я не могу использовать 'Output' метод из моего консольного приложения. Я компилирую .dll и перемещаю его в свой консольный проект. Есть ли дополнительный шаг между CreateInstance и возможность использования методов?

Это класс в моей DLL:

namespace DLL
{
    using System;

    public class Class1
    {
        public void Output(string s)
        {
            Console.WriteLine(s);
        }
    }
}

и вот приложение, которое я хочу загрузить DLL

namespace ConsoleApplication1
{
    using System;
    using System.Reflection;

    class Program
    {
        static void Main(string[] args)
        {
            var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");

            foreach(Type type in DLL.GetExportedTypes())
            {
                var c = Activator.CreateInstance(type);
                c.Output(@"Hello");
            }

            Console.ReadLine();
        }
    }
}
4b9b3361

Ответ 1

Члены должны быть разрешены во время компиляции, которые должны быть вызваны непосредственно из С#. В противном случае вы должны использовать отражение или динамические объекты.

Отражение

namespace ConsoleApplication1
{
    using System;
    using System.Reflection;

    class Program
    {
        static void Main(string[] args)
        {
            var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");

            foreach(Type type in DLL.GetExportedTypes())
            {
                var c = Activator.CreateInstance(type);
                type.InvokeMember("Output", BindingFlags.InvokeMethod, null, c, new object[] {@"Hello"});
            }

            Console.ReadLine();
        }
    }
}

Динамический (.NET 4.0)

namespace ConsoleApplication1
{
    using System;
    using System.Reflection;

    class Program
    {
        static void Main(string[] args)
        {
            var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");

            foreach(Type type in DLL.GetExportedTypes())
            {
                dynamic c = Activator.CreateInstance(type);
                c.Output(@"Hello");
            }

            Console.ReadLine();
        }
    }
}

Ответ 2

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

class Program
{
    static void Main(string[] args)
    {
        var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");

        var theType = DLL.GetType("DLL.Class1");
        var c = Activator.CreateInstance(theType);
        var method = theType.GetMethod("Output");
        method.Invoke(c, new object[]{@"Hello"});

        Console.ReadLine();
    }
}

Ответ 3

Вам нужно создать экземпляр типа, который выставляет метод Output:

static void Main(string[] args)
    {
        var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");

        var class1Type = DLL.GetType("DLL.Class1");

        //Now you can use reflection or dynamic to call the method. I will show you the dynamic way

        dynamic c = Activator.CreateInstance(class1Type);
        c.Output(@"Hello");

        Console.ReadLine();
     }

Ответ 4

Activator.CreateInstance() возвращает объект, который не имеет метода вывода.

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

Поскольку вы загружаете определенную DLL из определенного места, возможно, вы просто хотите добавить ее в качестве ссылки на консольное приложение?

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

Что-то вроде type.GetMethod("Output").Invoke(c, null); должно это сделать.

Ответ 5

Это не так сложно.

Вы можете проверить доступные функции загруженного объекта, и если вы найдете тот, который вы ищете по имени, затем просмотрите его ожидаемые части, если они есть. Если это вызов, который вы пытаетесь найти, вызовите его с помощью метода Invoke объекта MethodInfo.

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

Это довольно простой материал.