SmartClient - помогите красиво сделать :-)
От: Unikode  
Дата: 02.01.07 08:39
Оценка:
Привет всем.
Помогите поизящнее сделать следующую задачу:
На диске(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;
        }
    }
}
Re: SmartClient - помогите красиво сделать :-)
От: Unikode  
Дата: 02.01.07 17:36
Оценка:
для 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;
        }

...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.