1

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

这种服务的应用程序根应该在服务的OnStart方法中组成,还是早于作为的一部分static void Main

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

一种方法真的比另一种更好,还是取决于,我的问题真的是基于意见的?

4

1 回答 1

2

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

程序.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;
        }
    }
}

作文.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()”中,组合都会再次执行。

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

于 2016-03-16T11:55:19.080 回答