我實現一個模塊系統,我的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()
{
}
}
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();
}
...
...
...
的問題是,當我修改的東西,在主應用程序域屬於(具體而言,增加一個新的bot到IrcBot.Bots收集,IrcBot.Bots.Add(_configuration.Id, bot);
)的IrcBot.Bots
計數二級AppDomain中只增加了,而不是主要的appdomain,因爲我希望它是。
做了一些Console.WriteLining後,我發現,調用IrcBot.Bots.Count
的Add
呼叫在二級AppDomain中返回1後,在主應用程序域的OnLoad
調用後直再次調用則返回0。這有一個災難性的效果,並導致其他隨後加載的模塊發生故障。 在輔AppDomain中更改AppDomain後,如何更新主AppDomain中的bot數目(除別的之外)?
我不是在我的答案有信心,所以我會張貼此作爲一個評論,而不是:)我不認爲你將能夠使用更新的靜態MarshalByRefObject的狀態,因爲在一個AppDomain中的變化將是不可見的其他AppDomains。創建包含共享狀態的某種「上下文」對象可能更容易在主域和子域之間傳遞,但是這條道路包含許多哀嚎和咬牙切齒。您可能會發現它更容易使用WCF命名管道以更加無縫的方式進行溝通,看http://stackoverflow.com/questions/50153/interprocess-communication-for-windows-in-c-net-2-0 – Juliet