2011-07-16 9 views
1

我實現一個模塊系統,我的C#IRC殭屍獲得在主應用程序域值。這些模塊是存儲在子目錄「模塊」中的.dll程序集,它們用於向機器人添加功能,例如在IRC上添加額外的命令。這些模塊被設計爲在運行時加載和卸載,因此我可以更新殭屍程序或修復錯誤,而無需重新啓動整個應用程序。調用方法和從一個二級域名

當前,模塊系統爲每個要加載的模塊創建一個新的AppDomain,並在名爲ModuleHelper的類中使用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英寸

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

的問題是,當我修改的東西,在主應用程序域屬於(具體而言,增加一個新的bot到IrcBot.Bots收集,IrcBot.Bots.Add(_configuration.Id, bot);)的IrcBot.Bots計數二級AppDomain中只增加了,而不是主要的appdomain,因爲我希望它是。

做了一些Console.WriteLining後,我發現,調用IrcBot.Bots.CountAdd呼叫在二級AppDomain中返回1後,在主應用程序域的OnLoad調用後直再次調用則返回0。這有一個災難性的效果,並導致其他隨後加載的模塊發生故障。 在輔AppDomain中更改AppDomain後,如何更新主AppDomain中的bot數目(除別的之外)?

+0

我不是在我的答案有信心,所以我會張貼此作爲一個評論,而不是:)我不認爲你將能夠使用更新的靜態MarshalByRefObject的狀態,因爲在一個AppDomain中的變化將是不可見的其他AppDomains。創建包含共享狀態的某種「上下文」對象可能更容易在主域和子域之間傳遞,但是這條道路包含許多哀嚎和咬牙切齒。您可能會發現它更容易使用WCF命名管道以更加無縫的方式進行溝通,看http://stackoverflow.com/questions/50153/interprocess-communication-for-windows-in-c-net-2-0 – Juliet

回答

相關問題