Привет всем.
Помогите поизящнее сделать следующую задачу:
На диске(http, ftp и.т.п.) есть некоторые файлы, с ничего не значащими расширениями. Только не спрашивайте, для чего это надо, долго рассказывать

Эти файлы есть возможность как-то различать, типа:
app.file — файл приложения
app.config — файл конфигурации приложения
dll1.file — библиотека 1
dll2.file — библиотека 2 и.т.п.
Надо из всего этого мусора запустить приложение. Я тут недавно уже поднимал постинг про App.config через Reflection, а вот сейчас озарение спустилось, кое-что набросал, и даже работает.
Прошу посмотреть код, наверняка как-то можно это все посимпатичнее сделать. Спасибо.
Всех с праздниками!
using System;
using System.Reflection;
using System.Security.Policy;
namespace MySmartClient
{
/// <summary>
/// Summary description for SmartClient.
/// </summary>
class SmartClient
{
/// <summary>
/// Запуск сборки из произвольного места с произвольным названием файлов
/// </summary>
/// <param name="args"></param>
[STAThread]
static void Main(string[] args)
{
// Не понял почему, но файл должен иметь расширение, какое угодно - иначе не работает :-)
string urlEXE = @"C:\Repository\app.file";
string urlDLL = @"C:\Repository\dll1.file";
// Задаем начальные установки нового домена приложений
AppDomainSetup ads = new AppDomainSetup();
ads.ApplicationBase = @"C:\Repository\";
ads.ConfigurationFile = @"C:\Repository\app.config";
ads.DisallowBindingRedirects = false;
ads.DisallowCodeDownload = true;
Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
Evidence evidence = new Evidence(baseEvidence);
evidence.AddAssembly("(assembly)");
evidence.AddHost("(host)");
// Создаем новый домен
AppDomain domain = AppDomain.CreateDomain("newDomain", evidence, ads);
// тут, естественно, цикл будет чтобы подключить все библиотеки.....
// *****************************************************************
// читаем интерфейс библиотеки
string[] classNames = getInterfaces(urlDLL);
// создаем экземпляр хотя бы одного класса
foreach(string className in classNames)
{
try
{
domain.CreateInstanceFrom(urlDLL, className);
break;
}
catch{}
}
// *****************************************************************
// грузим приложение
domain.ExecuteAssembly(urlEXE);
}
/// <summary>
/// Получаем все public классы библиотеки
/// </summary>
/// <param name="file">URL библиотеки</param>
/// <returns></returns>
static string[] getInterfaces(string url)
{
System.Collections.ArrayList list = new System.Collections.ArrayList();
Assembly assemblyContent = Assembly.LoadFrom(url);
Type[] types = assemblyContent.GetTypes();
foreach(Type type in types)
{
if(type.IsClass && type.IsPublic) list.Add(type.FullName);
}
string[] result = new string[list.Count];
list.CopyTo(result);
return result;
}
}
}
для Singleton-ов пришлось немного доделать код (ниже)
Только вот у меня сомнения закрались, а правильно ли я "подключаю" библиотеки??? Это вообще так делается или есть какой-то более верный способ?
[STAThread]
static void Main(string[] args)
{
...
// тут, естественно, цикл будет чтобы подключить все библиотеки.....
// *****************************************************************
// читаем интерфейс библиотеки
foreach(string className in classNames)
{
try
{
domain.CreateInstanceFrom(urlDLL, className);
break;
}
catch
{
if(sigletonLoad(urlDLL, className)) break;
}
}
// *****************************************************************
...
}
/// <summary>
///
/// </summary>
/// <param name="url"></param>
/// <param name="className"></param>
/// <returns></returns>
static bool sigletonLoad(string url, string className)
{
bool success = false;
try
{
Assembly assemblyContent = Assembly.LoadFrom(url);
Type type = assemblyContent.GetType(className);
MethodInfo[] methods = type.GetMethods();
foreach(MethodInfo method in methods)
{
try
{
if(method.Name.ToLower().EndsWith("getinstance") && method.IsStatic)
{
method.Invoke(null, null);
success = true;
break;
}
}
catch{}
}
}
catch{}
return success;
}
...