Приветствую всех, не секрет иногда все мы используем сторонние библиотеки, и порой нарушая их условия использования, скрываем в недрах нашего приложения. Или же мы просто не хотим таскать их за своим приложением exe, что бы они не мозолили глаза. В таком случаи мы можем их добавить в сборку и использовать методы и классы находящиеся внутри них. Сделать это можно следующим способом.
Добавляем dll в папку ресурсы:
Допусти мы имеет dll в моем случаи у нее содержимое такое:
using System;
using System.Windows.Forms;
namespace MyClass
{
public class Class1
{
public void MyMethod()
{
MessageBox.Show("www.nookery.ru");
}
}
}
Теперь мы добавим нашу dll в новый проект, сделать это можно следующим образом:

Выделить наш проект, нажав правую кнопку мыши выбрать свойство.

Нажмите расширяющий значок треугольника и выберите Добавить существующий фаил. Теперь укажите ваш dll он добавится в ресурсы.

После чего вам нужно его сохранить, для этого выберите пункт меню Фаил и Сохранить выбранные элементы.
Теперь мы можем закрыть, это окно, а в обозревателе решений мы должны увидеть :

На этом все, наша dll находится внутри сборки, однако нам теперь нужно ее как то использовать, а вот для этого имеется несколько вариантов.
1. Вариант с помощью Рефлексии:
using System;
using System.Reflection;
namespace nookery
{
class Program
{
static void Main(string[] args)
{
Assembly asm = Assembly.Load(nookery.Properties.Resources.MyClass);
dynamic myClass = asm.CreateInstance("MyClass.Class1");
myClass.MyMethod();
Console.ReadKey();
}
}
}
Не достатком такого варианта это отсутствие intellisense при работе с dll, нам необходимо знать метод вызываемый, класс и пространство имен. Хотя это можно узнать все и через Рефлексию, так же. Однако если проект очень большой и использует большое количество dll, может стать препятствием.
2. Вариант с помощью AppDomain подменить утерянные ссылки на dll.
- Первый вариант с использованием winform
У нас имеется тот же класс в dll :
using System;
using System.Windows.Forms;
namespace MyClass
{
public class Class1
{
public void MyMethod()
{
MessageBox.Show("www.nookery.ru");
}
}
}
Описанным выше примере, мы добавляем в ресурсы dll, и указываем как обычно ссылку на ее месторасположения, продолжая работать словно так как будто ничего не предвещает.
Однако нам придется создать событие и обработать ее, пример ниже показывает как это сделать:
using System;
using System.Reflection;
using System.Windows.Forms;
using WindowsFormsApp19.Properties;
namespace WindowsFormsApp19
{
public partial class Form1 : Form
{
public Form1()
{
AppDomain.CurrentDomain.AssemblyResolve += AppDomain_AssemblyResolve;
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MyClass.Class1 my = new MyClass.Class1(); //обычная работа с классом
my.MyMethod(); //тут мы вызываем как обычно метод из dll
}
private static Assembly AppDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
if (args.Name.Contains("MyClass")) //имя dll
return Assembly.Load(Resources.MyClass); //расположения dll в папке ресурсы
return null;
}
}
}
Собираем проект, и переносим наш exe куда угодно. При запуске приложения сработает событие, из за того, что не был обнаружен фаил dll который мы указывали когда добавляли ссылку на него. И внутри обработчика событий у нас происходит подмена ссылок, а программа продолжает свою работу.
Не забудьте в свойствах dll изменить действие при сборке на Внедренный ресурс.

- Теперь рассмотрим другой вариант с Console:
Из за особенностей работы метода Main, а именно то что она начинает работать самым первым, в нем нельзя подписываться на событие иначе, обработка события не произойдет. Для решения этого есть два варианта либо так :
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Reflection;
using MyClass;
using ConsoleApp51.Properties;
namespace nookery
{
class Program
{
static Program(){
AppDomain.CurrentDomain.AssemblyResolve += AppDomain_AssemblyResolve;
}
private static void Main()
{
MyClass.Class1 my = new MyClass.Class1();
my.MyMethod();
Console.ReadKey();
}
private static Assembly AppDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
if (args.Name.Contains("MyClass")) //имя dll
return Assembly.Load(Resources.MyClass); //расположения dll в папке ресурсы
return null;
}
}
}
используя статический конструктор, который отработает раньше метода Main
либо вот так:
using System;
using System.Reflection;
using ConsoleApp51.Properties;
namespace nookery
{
class Program
{
private static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += AppDomain_AssemblyResolve;
Test();
}
public static void Test()
{
MyClass.Class1 my = new MyClass.Class1();
my.MyMethod();
}
private static Assembly AppDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
if (args.Name.Contains("MyClass")) //имя dll
return Assembly.Load(Resources.MyClass); //расположения dll в папке ресурсы
return null;
}
}
}
Создав вспомогательный метод вынеся в него работу метода из dll
3. Выгрузить все DLL рядом с exe после запуска.
File.WriteAllBytes("MyClass.dll", ConsoleApp51.Properties.Resources.MyClass);
[DllImport("MyClass.dll", SetLastError = true, EntryPoint = "MyMethod", ExactSpelling = true)]
public static extern void MyMethod();
Однако этот вариант работает только с не управляемым кодом который написан на C++, и нам не походит.
