我正在开发一个非常简单的通用主机解决方案,它允许我们将程序集作为 Windows 服务(ala NServiceBus)进行托管。我遇到以下异常(类似于 Dru 的 博客文章)。我需要它才能工作,以便我可以在不同的应用程序域中托管服务。
“在程序集“MyProject.WindowsServices.GenericHost,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”中键入“MyProject.WindowsServices.GenericHost.Program+<>c__DisplayClass5”未标记为可序列化。”
我使用的是 Topshelf 1.0 RC 二进制文件,可从 topshelf 主页 (topshelf-project.com) 上的下载链接获取。我已经尝试了最新版本(29/07/2010),并且可以从 google code 和 github 下载该版本!我无法让他们中的任何一个为我工作!
这在具有旧版本 Topshelf 的 NServiceBus 库中工作(dll 版本为 0.8.0.96)。通过对下面的内容进行一些小的代码更改(使用 CreateServiceLocator 代替 HowToBuildService),它对我来说适用于这些较旧的二进制文件,但我宁愿坚持使用最新的代码以利用任何计划的修复或增强功能。
这是我的代码。
static void Main(string[] args)
{
ArgumentParser arguments = new ArgumentParser(args);
string configFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
arguments.ServiceType.Assembly.ManifestModule.Name + ".config");
RunConfiguration cfg = RunnerConfigurator.New(x =>
{
x.SetServiceName(arguments.ServiceName);
x.SetDisplayName(arguments.DisplayName);
x.SetDescription(arguments.Description);
if (string.IsNullOrEmpty(arguments.UserName))
{
x.RunAsLocalSystem();
}
else
{
x.RunAs(arguments.UserName, arguments.Password);
}
x.ConfigureServiceInIsolation<GenericHost>(c =>
{
c.ConfigurationFile(configFile);
c.Named(arguments.ServiceType.AssemblyQualifiedName);
c.HowToBuildService(name => new GenericHost(arguments.ServiceType));
c.WhenStarted(tc => tc.Start());
c.WhenStopped(tc => tc.Stop());
});
});
Runner.Host(cfg, args);
}
另外值得注意的是,我的 GenericHost 类和由 argument.ServiceType 标识的类都实现了 MarshalByRefObject,并且我还使这些类可序列化以查看是否有帮助。不过,并不是这些类导致了问题,它似乎在抱怨 C# 编译器为我配置的一个或多个 lambda 生成的匿名类型。
还有其他人在使用ConfigureServiceInIsolation()时遇到这个问题吗?如果没有,有人知道我在这里缺少什么吗?如果您需要更多信息,例如堆栈跟踪或更多代码,请告诉我。
I am developing a very simple Generic Host solution that will allow us to host assemblies as windows services (ala NServiceBus). I'm coming across the following exception (similar to the comments mentioned on Dru's blog post). I need this to work so I can host services in different AppDomains.
"Type 'MyProject.WindowsServices.GenericHost.Program+<>c__DisplayClass5' in Assembly 'MyProject.WindowsServices.GenericHost, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable."
I'm using the Topshelf 1.0 RC binaries available from the download link on the topshelf homepage (topshelf-project.com). I've tried the latest build (29/07/2010), and the builds avialable for download from google code and github! I can't get any of them to work for me!
This is working in the NServiceBus library with an older version of Topshelf (the dll is versioned 0.8.0.96). With some minor code changes to what I have below (use CreateServiceLocator in place of HowToBuildService) it works for me with these older binaries, but I'd rather stick to the latest code to take advantage of any planned fixes or enhancements.
Here is my code.
static void Main(string[] args)
{
ArgumentParser arguments = new ArgumentParser(args);
string configFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
arguments.ServiceType.Assembly.ManifestModule.Name + ".config");
RunConfiguration cfg = RunnerConfigurator.New(x =>
{
x.SetServiceName(arguments.ServiceName);
x.SetDisplayName(arguments.DisplayName);
x.SetDescription(arguments.Description);
if (string.IsNullOrEmpty(arguments.UserName))
{
x.RunAsLocalSystem();
}
else
{
x.RunAs(arguments.UserName, arguments.Password);
}
x.ConfigureServiceInIsolation<GenericHost>(c =>
{
c.ConfigurationFile(configFile);
c.Named(arguments.ServiceType.AssemblyQualifiedName);
c.HowToBuildService(name => new GenericHost(arguments.ServiceType));
c.WhenStarted(tc => tc.Start());
c.WhenStopped(tc => tc.Stop());
});
});
Runner.Host(cfg, args);
}
Also of note is that my GenericHost class and the class identified by arguments.ServiceType both implement MarshalByRefObject and I have also made these classes Serializable to see if that would help. It's not these classes that are causing the problem though, it appears to be complaining about an anonymous type generated by the C# compiler for one or more of the lambda's I have configured.
Is anyone else seeing this problem with using ConfigureServiceInIsolation()? If not, does anyone know what I'm missing here? Let me know if you need more info, e.g. stack trace or more code.
发布评论
评论(1)
如果您只在主机内使用一项服务,我会删除“InIsolation”。它不能正常工作,但在 TopShelf 的未来版本中(我们目前正在研究它)我认为我们对这个问题有更好的答案。除了能够将文件拖放到主机中并自动在新的 AppDomain 中启动您的服务之外。
我想说这属于一个已知问题,除非有令人信服的理由使用隔离,否则暂时避免使用它。您无法跨应用程序域障碍编组 lambda 表达式,因此您会看到问题。如果隔离问题足够重要,我可以在我们计划发布最新版本之前研究解决该问题的努力与时间表。 [您可以获取最新的开发版本。来自这里的位: http://github.com/legomaster/Topshelf -- 警告,我们仍在积极开发中,但我认为所有主要错误现在都已被消除]。
如果您想进一步讨论此问题,最简单的方法可能是在所有开发人员都在关注的 MassTransit 列表上发布:http://groups.google.com/group/masstransit-discuss
我希望这有帮助!
If you're only using one service inside the host, I would remove the "InIsolation". It doesn't work right but in a future version of TopShelf (we are currently working on it) I think we have a better answer for this issue. On top of the ability to just drop files in a host and have that spin up your service in a new AppDomain automagically.
I would say this falls under a know issue and unless there's a compelling reason to use the InIsolation avoid it for the moment. You can't marshal lambda expressions across app domain barriers, hence the issue you're seeing. If the InIsolation issue is important enough, I can look into the effort to fix that vs. the timeline before we plan on releasing the newest version. [You can grab the latest dev. bits from here: http://github.com/legomaster/Topshelf -- warning, we're still under active development but I think all the major bugs are now squashed].
If you want to discuss this further, it might be easiest to post on the MassTransit list where all the developers are watching: http://groups.google.com/group/masstransit-discuss
I hope this helps!