簡體   English   中英

從輔助域調用主應用域中的方法並獲取值

[英]Calling methods and getting values in the main appdomain from a secondary domain

我正在為我的 C# IRC Bot 實現一個模塊系統。 這些模塊是.dll 程序集,它們存儲在子目錄“模塊”中,它們用於向機器人添加功能,例如在 IRC 上添加額外的命令。 這些模塊設計為在運行時加載和卸載,因此我可以更新機器人或修復錯誤,而無需重新啟動整個應用程序。

目前,模塊系統為每個要加載的模塊創建一個新的AppDomain ,並在名為ModuleHelper的 class 中使用CreateInstanceFromAndUnwrap創建一個代理。

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()
    {
    }
}

在加載或卸載模塊時調用OnLoadOnUnload 模塊也從外部程序集中的MarshalByRefObject繼承,例如模塊ConfigurationReader.dll中的這個 class 。

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();
    }
...
...
...

問題是,當我修改屬於主 appdomain 的內容時(具體來說,將新機器人添加到 IrcBot.Bots 集合中, IrcBot.Bots.Add(_configuration.Id, bot); )內部的IrcBot.Bots計數會增加僅輔助應用程序域,而不是我想要的主應用程序域。

在做了一些 Console.WriteLining 之后,我發現在輔助 appdomain 中的Add調用返回 1 之后調用IrcBot.Bots.Count ,並在主 appdomain 中的OnLoad調用返回 0 之后再次調用它。這有一個災難性的效果,並導致之后加載的其他模塊發生故障。 在輔助 AppDomain 中更改后,如何更新主 AppDomain 中的機器人計數(除其他外)?

正如朱麗葉所說,AppDomain 確實是隔離的,因此“靜態”變量對其他 AppDomain 不可見。 解決方案可能是使用跨 AppDomain 單例,如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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM