Как я могу динамически загружать и выгружать сборки .Net внутри службы WCF

Я хочу разработать веб-службу wcf, размещенную в службе Windows, которая будет вести себя как служба управления выполнением задач и создания отчетов. Каждая задача будет представлена ​​в виде сборки .net, имя задачи и путь к dll будут в центральной конфигурации. В задаче в первую очередь должны быть как минимум методы Execute и Stop. Должна быть возможность загружать, выполнять, останавливать и выгружать задачи во время работы службы wcf и выполнения других задач. Одновременно может выполняться один экземпляр каждой задачи. Одна задача, имеющая исключение, не должна прерывать другие задачи. Я думаю о таких методах, как

[OperationContract]    
bool Load(string taskName);
[OperationContract]
bool Run(string taskName);

Я думаю о том, как я могу выполнять эти задачи загрузки и выгрузки по требованию, а также изоляцию. Некоторые варианты будут использовать Reflection, MAF (System.Addin) и т. д. Первоначальный удар по производительности для загрузки приемлем, поскольку эта загрузка/выгрузка будет происходить очень редко.

Каков наилучший способ (библиотека, API, фреймворк и т. д.) для достижения этой цели.


person softveda    schedule 09.05.2011    source источник


Ответы (2)


Не могу сказать о лучшем, но ЕДИНСТВЕННЫЙ (!) подход предполагает использование нескольких доменов приложений. Поскольку вы НЕ можете выгрузить сборку, только домен приложения, поэтому все сборки, принадлежащие задаче, должны быть загружены в отдельный домен приложения.

Это технически очень тривиально сделать. Дьявол кроется в деталях. MAF может быть хорошей основой для этого.

person TomTom    schedule 09.05.2011

Я бы просто определил интерфейс, который должна реализовать каждая поставляемая сборка.

Я работаю над проектом, который реализует поведение конвейера, этот фрагмент кода может быть вам полезен: он использует linq для поиска во всех загруженных сборках классов, реализующих определенный интерфейс и имеющих пустой конструктор и настраиваемый атрибут (вы можете не нужна часть пользовательского атрибута) - и он создает экземпляр каждого найденного элемента.

Я понимаю, что это не совсем то, что вам нужно, но, надеюсь, это укажет вам правильное направление - надеюсь, это поможет :)

        var processingModules = from mod in
                                   AppDomain.CurrentDomain.GetAssemblies().SelectMany(assembly =>
                                   {

                                       return from t in assembly.GetTypes()

                                              where 
                                                    t.GetInterfaces().Contains(typeof(IProcessingModule<T>))
                                                    && t.GetConstructor(Type.EmptyTypes) != null
                                                    && t.GetCustomAttributes(typeof(ProcessModuleAttribute), true)
                                                           .Cast<ProcessModuleAttribute>()
                                                           .Select(e => e.Processes.Contains(manager.Name))
                                                           .Contains(true)

                                              select Activator.CreateInstance(t) as IProcessingModule<T>;
                                   })
                                   orderby mod.ModuleOrder
                                       select mod;
person Nathan    schedule 09.05.2011