何时在 windows 服务中组合应用程序根目录
When to compose application root in a windows service
给定将 运行 作为 windows 服务的 C# 控制台应用程序,有大约 2 个应用程序入口点。第一个明显的是 static void Main
方法。此方法的部分工作是安装扩展 ServiceBase
的东西,然后 运行 它以调用其 OnStart
方法。还有更高级别的工具,如 Topshelf,可帮助您避免较低级别的 ServiceBase
实现,但您最终还是会得到 2 个潜在的应用程序入口点:static void Main
和某种 OnStart
方法.
此类服务的应用程序根应该在服务的 OnStart
方法中组成,还是早于 static void Main
的一部分?
似乎在服务的 OnStart
方法中进行组合(并在 OnStop
方法中销毁/处置它)可能会有优势,因为重新启动服务会随后组合一个新的应用程序根目录.我在这里看到的唯一真正的缺点是,如果我使用像 Topshelf 这样的工具,我不能使用 DI 容器来获取我的服务实例 class。再一次,这可能不是一个真正的缺点。尽管如此,我阅读的大多数应用程序都是在 Main
期间构成根的,而不是在 OnStart
期间,我不确定为什么。
一种方法真的比另一种更好吗,或者它取决于,我的问题真的是一个基于意见的问题吗?
我认为这与其说是事实,不如说是一种观点,但我更喜欢在服务构建期间进行组合,然后使用 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();
}
The only real disadvantage I can see here is that if I am using a tool like Topshelf, I can't use the DI container to obtain an instance of my Service class
这是真的,但您不需要访问 program.cs 代码,只需访问 MyService 代码,它将代表您服务的实际 "core" 代码。
此外,当您停止服务时,您实际上会杀死它(除非您暂停它),因此无论您是否将其放入 "onStart()" 中,组合都会再次执行。
像往常一样,恕我直言。 :)
给定将 运行 作为 windows 服务的 C# 控制台应用程序,有大约 2 个应用程序入口点。第一个明显的是 static void Main
方法。此方法的部分工作是安装扩展 ServiceBase
的东西,然后 运行 它以调用其 OnStart
方法。还有更高级别的工具,如 Topshelf,可帮助您避免较低级别的 ServiceBase
实现,但您最终还是会得到 2 个潜在的应用程序入口点:static void Main
和某种 OnStart
方法.
此类服务的应用程序根应该在服务的 OnStart
方法中组成,还是早于 static void Main
的一部分?
似乎在服务的 OnStart
方法中进行组合(并在 OnStop
方法中销毁/处置它)可能会有优势,因为重新启动服务会随后组合一个新的应用程序根目录.我在这里看到的唯一真正的缺点是,如果我使用像 Topshelf 这样的工具,我不能使用 DI 容器来获取我的服务实例 class。再一次,这可能不是一个真正的缺点。尽管如此,我阅读的大多数应用程序都是在 Main
期间构成根的,而不是在 OnStart
期间,我不确定为什么。
一种方法真的比另一种更好吗,或者它取决于,我的问题真的是一个基于意见的问题吗?
我认为这与其说是事实,不如说是一种观点,但我更喜欢在服务构建期间进行组合,然后使用 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();
}
The only real disadvantage I can see here is that if I am using a tool like Topshelf, I can't use the DI container to obtain an instance of my Service class
这是真的,但您不需要访问 program.cs 代码,只需访问 MyService 代码,它将代表您服务的实际 "core" 代码。
此外,当您停止服务时,您实际上会杀死它(除非您暂停它),因此无论您是否将其放入 "onStart()" 中,组合都会再次执行。
像往常一样,恕我直言。 :)