Question

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.

Was it helpful?

Solution

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!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top