Хорошо, вот сделка:
Я хочу загрузить пользовательский Assembly
в мои AppDomain
, , но Я хочу сделать это, только если указано Assembly
соответствует некоторым требованиям.В моем случае, он должен иметь, среди прочих требований, Assembly
уровень Attribute
, который мы могли бы назвать MandatoryAssemblyAttribute
.
Есть два пути, которые я могу пройти, насколько я вижу:
Загрузите Assembly
в мой текущий домен приложений и проверьте, присутствует ли Attribute
.Легко, но неудобно, так как я застрял с загруженной сборкой, даже если у нее нет MandatoryAssemblyAttribute
.Не хорошо.
Я могу создать новый AppDomain
и загрузить оттуда Assembly
и проверить, присутствует ли мой старый добрый MandatoryAddemblyAttribute
.Если это так, сбросьте созданный AppDomain и продолжайте загружать Assembly
в мой CurrentAppDomain
, если нет, просто сбросьте новый AppDomain
, сообщите пользователю и попросите его повторить попытку.
Легче сказать, чем сделать.Выполняя поиск в Интернете, я нашел несколько примеров того, как это сделать, включая предыдущий вопрос, опубликованный в SO: Загрузка DLL в отдельный домен приложений
Проблема, с которой я сталкиваюсьэто решение заключается в том, что вы на самом деле должны знать тип (полное имя) в Assembly
, который вы хотите загрузить для начала.Это не решение, которое мне нравится.Главное - попытаться подключить произвольный Assembly
, который соответствует некоторым требованиям, и с помощью атрибутов определить, какие типы использовать.Заранее неизвестно, какие типы будут у Assembly
.Конечно, я мог бы сделать требование, чтобы любой Assembly
, предназначенный для использования таким образом, реализовывал некоторый фиктивный класс, чтобы предложить "точку входа" для CreateInstanceFromAndUnwrap
.Я бы предпочел не делать этого.
Кроме того, если я продолжу и сделаю что-то в этом направлении:
using (var frm = new OpenFileDialog())
{
frm.DefaultExt = "dll";
frm.Title = "Select dll...";
frm.Filter = "Model files (*.dll)|*.dll";
answer = frm.ShowDialog(this);
if (answer == DialogResult.OK)
{
domain = AppDomain.CreateDomain("Model", new Evidence(AppDomain.CurrentDomain.Evidence));
try
{
domain.CreateInstanceFrom(frm.FileName, "DummyNamespace.DummyObject");
modelIsValid = true;
}
catch (TypeLoadException)
{
...
}
finally
{
if (domain != null)
AppDomain.Unload(domain);
}
}
}
Это будет хорошо работать, но если тогда я продолжу и сделаю следующее:
foreach (var ass in domain.GetAssemblies()) //Do not fret, I would run this before unloading the AppDomain
Console.WriteLine(ass.FullName);
Я получаю FileNotFoundException
.Почему?
Другой путь, по которому я мог бы пойти: Как загрузить DLL в отдельный домен приложений Но мне тоже не повезло.Я получаю FileNotFoundException
всякий раз, когда выбираю какой-то случайный .NET Assembly
, и кроме того, он отрицает цель, так как мне нужно знать имя сборки (не имя файла), чтобы загрузить его, что не соответствует моим требованиям.
Есть ли другой способ сделать этот запрет MEF
(я не ориентируюсь на .NET 3.5)?Или я застрял с созданием какого-то фиктивного объекта для загрузки с Assembly
по CreateInstanceFromAndUnwrap
?И если да, то почему я не могу перебрать загруженные сборки, не получив FileNotFoundException
?Что я делаю не так?
Большое спасибо за любые советы.