何时在Windows服务中组合应用程序根目录

时间:2016-03-10 10:02:53

标签: c# windows-services topshelf compositionroot

鉴于将作为Windows服务运行的C#控制台应用程序,有两种应用程序入口点。第一个明显的方法是static void Main方法。此方法的部分工作是安装扩展ServiceBase的内容然后运行它以获取其OnStart方法。还有像Topshelf这样的更高级别的工具可以帮助您避免低级ServiceBase实施,但最终仍然有2个潜在的应用程序入口点:static void Main和某种OnStart方法

此类服务的应用程序根目录是否应该在服务的OnStart方法中组合,或者早于static void Main的一部分?

似乎在服务的OnStart方法中进行编写(并在OnStop方法中销毁/处理它)可能会有一个优势,因为重新启动服务会构成一个新的应用程序根。我在这里看到的唯一真正的缺点是,如果我使用像Topshelf这样的工具,我不能使用DI容器来获取我的Service类的实例。然而,这可能不是一个真正的劣势。尽管如此,我读到的大多数应用程序在Main期间构成根,而不是在OnStart期间,我不确定原因。

一种方法真的比另一种方法好,还是取决于哪种方式,我的问题实际上是基于意见的方法?

1 个答案:

答案 0 :(得分:2)

我认为这不是一个事实而是一个事实,但我更喜欢在服务构建期间撰写,然后使用OnStart()来激活我之前编写的服务。这是我通常的工作方式(使用Topshelf)。例如:

<强> Program.cs的

public class Program
{
    private static ILifetimeScope _scope;
    private static readonly ILog Log = LogManager.GetLogger(typeof(Program));

    public static void Main(string[] args)
    {
        try
        {
            XmlConfigurator.Configure();

            // configure composition
            _scope = CompositionRoot.CreateScope();

            HostFactory.Run(x =>
            {
                x.UseLog4Net();
                x.UseAutofacContainer(_scope);

                x.Service<IMyService>(svc =>
                {
                    svc.ConstructUsingAutofacContainer();
                    svc.WhenStarted(tc => tc.Start());
                    svc.WhenStopped(tc =>
                    {
                        tc.Stop();
                        _scope.Dispose();
                    });
                });

                x.RunAsNetworkService();
                x.StartManually();
            });
        }
        catch (Exception e)
        {
            Log.Error("An error occurred during service construction.", e);
            throw;
        }
    }
}

<强> composition.cs

internal class CompositionRoot
{
    public static ILifetimeScope CreateScope()
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<MyService>().As<IMyService>().SingleInstance();
        // other things you want to register

        return builder.Build();
    }
}

<强> imyservice.cs

public interface IMyService
{
    void Start();
    void Stop();
}
  

我在这里看到的唯一真正的缺点是,如果我使用像Topshelf这样的工具,我不能使用DI容器来获取我的Service类的实例

这是事实,但您无需访问program.cs代码,只需访问MyService代码,该代码将代表您服务的实际“核心”代码。

同样当你停止服务时你会实际杀死它(除非你暂停它),所以无论你是否把它放在“onStart()”内,它都会再次执行。

像往常一样,恕我直言。 :)