Вызов методов и получение значений в главном домене приложения из вторичного домена - PullRequest
1 голос
/ 16 июля 2011

Я внедряю модульную систему для моего C # IRC Bot.Модули - это сборки .dll, которые хранятся в подкаталоге «модули», и они используются для добавления функциональности боту, например, добавления дополнительных команд в IRC.Эти модули предназначены для загрузки и выгрузки во время выполнения, поэтому я могу обновлять бота или исправлять ошибки, без необходимости перезапускать все приложение.

В настоящее время система модулей создает новый AppDomain для каждого модуля, который будетзагружен, и прокси должен быть создан с использованием CreateInstanceFromAndUnwrap внутри класса с именем ModuleHelper.

AppDomain domain = AppDomain.CreateDomain(name, null, new AppDomainSetup 
{ 
    ApplicationName = AppDomain.CurrentDomain.SetupInformation.ApplicationName,
    ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
    DisallowApplicationBaseProbing = true,
    PrivateBinPathProbe = ModuleDirectory,
    PrivateBinPath = ModuleDirectory,
    ShadowCopyDirectories = ModuleDirectory,
    CachePath = Path.Combine(ModuleDirectory, "cache"),
    ShadowCopyFiles = bool.TrueString 
});
ModuleProxy proxy = null;
try
{
    proxy = (ModuleProxy)domain.CreateInstanceFromAndUnwrap(location, AssemblyName.GetAssemblyName(location).Name + ".Module");
    proxy.OnLoad();
}
catch
{
    AppDomain.Unload(domain);
    throw;
}

Этот прокси наследуется от MarshalByRefObject.

public abstract class ModuleProxy : MarshalByRefObject
{
    internal protected virtual void OnLoad()
    {
    }

    internal protected virtual void OnUnload()
    {
    }
}

OnLoad иOnUnload вызывается, когда модуль загружен или выгружен.Модули также наследуются от MarshalByRefObject во внешней сборке, такой как этот класс в модуле, ConfigurationReader.dll.

public class Module : ModuleProxy
{
    private Configuration _configuration = new Configuration();

    protected override void OnLoad()
    {
        string fileName = Path.Combine(ModuleHelper.ModuleDirectory, AssemblyName.GetAssemblyName(Assembly.GetExecutingAssembly().Location).Name + ".conf");
        _configuration.ReadAndLoadConfiguration(fileName);
        IrcBot bot = new IrcBot(_configuration);
        if (_configuration.Perform != null)
        {
            bot.EventManager.OnRegister += PerformOnRegister;
        }
        if (!string.IsNullOrWhiteSpace(_configuration.IdentifyMatchPeer + _configuration.IdentifyMatchText + _configuration.IdentifyPassword))
        {
            bot.EventManager.OnNotice += IdentifyOnNotice;
        }
        IrcBot.Bots.Add(_configuration.Id, bot);
        IrcBot.Bots[_configuration.Id].Start();
    }
...
...
...

Проблема заключается в том, что когда я изменяю то, что принадлежит основному домену приложения (в частности,добавив нового бота в коллекцию IrcBot.Bots, IrcBot.Bots.Add(_configuration.Id, bot);) счетчик IrcBot.Bots увеличивается только внутри вторичного домена приложения, а не основного домена приложения, как я хочу.

После небольшого выполненияConsole.WriteLining, я обнаружил, что вызов IrcBot.Bots.Count после вызова Add во вторичном домене приложения возвращает 1, и повторный вызов сразу после того, как вызов OnLoad в главном домене приложения возвращает 0. Это имеет катастрофический эффект,и вызывает неисправность других модулей, которые впоследствии загружаются. Как я могу обновить количество ботов (помимо прочего) в главном домене приложений после его изменения во вторичном домене приложений?

1 Ответ

0 голосов
/ 16 июля 2011

Как сказала Джульетта, домены приложений действительно изолированы, поэтому «статические» переменные не видны из других доменов приложений.Решением может быть использование кросс-доменных синглетонов, как объяснено в http://jonathan.dickinsons.co.za/blog/2010/11/cross-domain-singleton-in-c/ и http://www.dolittle.com/blogs/einar/archive/2007/05/18/cross-appdomain-singleton.aspx.

...