Reputation: 201
In Autofac I can do the following
builder
.RegisterType<Services.GreetService>()
.As<ServiceBase>()
.InstancePerLifetimeScope();
Where GreetService inherits from ServiceBase
I would like to do the same sort of thing with Simple Injector.
Does anybody know how?
Thanks
Update 1
I found this article where they use autofac in a windows service: http://www.turbulentintellect.com/2011/02/anatomy-of-windows-service-part-2.html
I have been trying to replace Autofac with Simple Injector but I can't get the resulting service to install. The error I receive is System.ArgumentException: Must specify value for source. This usually points to the ServiceName not matching in the ServiceInstaller and the Service.
Everything is set up as per the article except the below:
internal class ServiceBootstrapper
{
//public IContainer Build()
//{
// var builder = new ContainerBuilder();
// builder
// .RegisterType<GreetService>()
// .As<ServiceBase>()
// .InstancePerLifetimeScope();
// builder
// .RegisterType<ServiceNameProvider>()
// .As<IServiceNameProvider>()
// .InstancePerLifetimeScope();
// builder
// .RegisterType<Greeter>()
// .As<IGreeter>()
// .InstancePerLifetimeScope();
// return builder.Build();
//}
public Container Build()
{
var container = new Container();
container.RegisterLifetimeScope<ServiceBase, GreetService>();
container.RegisterLifetimeScope<IServiceNameProvider, ServiceNameProvider>();
container.RegisterLifetimeScope<IGreeter, Greeter>();
container.Verify();
return container;
}
}
internal class InstallBootstrapper
{
//public IContainer Build()
//{
// var builder = new ContainerBuilder();
// builder
// .RegisterType<HelloServiceProcessInstaller>()
// .As<Installer>()
// .InstancePerLifetimeScope();
// builder
// .RegisterType<GreetServiceInstaller>()
// .As<Installer>()
// .InstancePerLifetimeScope();
// builder
// .RegisterType<Config.ServiceNameProvider>()
// .As<Config.IServiceNameProvider>()
// .InstancePerLifetimeScope();
// return builder.Build();
//}
public Container Build()
{
var container = new Container();
container.RegisterLifetimeScope<HelloServiceProcessInstaller>();
container.RegisterLifetimeScope<GreetServiceInstaller>();
container.RegisterLifetimeScope<IServiceNameProvider, ServiceNameProvider>();
container.Verify();
return container;
}
}
public static class Program
{
public static void Main(String[] args)
{
var iocBootstrap = new ServiceBootstrapper();
var container = iocBootstrap.Build();
var services = container.GetInstance<ServiceBase>();
ServiceBase.Run(services);
//var services = container.Resolve<IEnumerable<ServiceBase>>();
//ServiceBase.Run(services.ToArray());
}
}
[RunInstaller(true)]
public class ProjectInstaller : Installer
{
public ProjectInstaller()
{
var bootstrapper = new InstallBootstrapper();
var container = bootstrapper.Build();
var processInstallers = container.GetInstance<ServiceProcessInstaller>();
var serviceInstaller = container.GetInstance<ServiceInstaller>();
//var installers = container.GetInstance<IEnumerable<Installer>>();
//var installers = container.Resolve<IEnumerable<Installer>>();
//Installers.AddRange(installers.ToArray());
Installers.Add(processInstallers);
Installers.Add(serviceInstaller);
}
}
I am definitely missing something here but can't seem to work out what.
Update 2
When I use InstallUtil to install the service I receive the below in the install log
Running a transacted installation.
Beginning the Install phase of the installation. See the contents of the log file for the C:\Local Development\HelloSvc\HelloSvc\bin\Debug\HelloSvc.exe assembly's progress. The file is located at C:\Local Development\HelloSvc\HelloSvc\bin\Debug\HelloSvc.InstallLog.
An exception occurred during the Install phase. System.ArgumentException: Must specify value for source.
The Rollback phase of the installation is beginning. See the contents of the log file for the C:\Local Development\HelloSvc\HelloSvc\bin\Debug\HelloSvc.exe assembly's progress. The file is located at C:\Local Development\HelloSvc\HelloSvc\bin\Debug\HelloSvc.InstallLog.
The Rollback phase completed successfully.
The transacted install has completed.
As previously mentioned this is usually do to the ServiceName being set incorrectly but I don't see how this is possible in this scenario.
Thanks
Upvotes: 3
Views: 1521
Reputation: 139748
You haven't described what problems do you have with the conversion, so I try to answer two possible question/problem:
Registering classes for their base classes also supported by Simple Injector with the Register
method:
var container = new Container();
container.Register<ServiceBase, GreetService>();
And if you have problem with the InstancePerLifetimeScope
part then you can find the similar LifetimeScopeLifestyle
in the Lifetime Scoping Extensions and you can use it with:
var container = new Container();
container.Register<ServiceBase, GreetService>(
new LifetimeScopeLifestyle());
or optionally the using the RegisterLifetimeScope
extension method from the same package:
var container = new Container();
container.RegisterLifetimeScope<ServiceBase, GreetService>();
Regarding you service installation problem:
In the InstallBootstrapper
you need to register the HelloServiceProcessInstaller
as ServiceProcessInstaller
and the GreetServiceInstaller
as ServiceInstaller
because later you try to resolve them as ServiceProcessInstaller
and ServiceInstaller
:
internal class InstallBootstrapper
{
public Container Build()
{
var container = new Container();
container.RegisterLifetimeScope<ServiceProcessInstaller,
HelloServiceProcessInstaller>();
container.RegisterLifetimeScope<ServiceInstaller,
GreetServiceInstaller>();
container.RegisterLifetimeScope<IServiceNameProvider,
ServiceNameProvider>();
container.Verify();
return container;
}
}
And in the ProjectInstaller
because of the RegisterLifetimeScope
you need to create a LifetimeScope with the `BeginLifetimeScope:
[RunInstaller(true)]
public class ProjectInstaller : Installer
{
public ProjectInstaller()
{
var bootstrapper = new InstallBootstrapper();
var container = bootstrapper.Build();
using(container.BeginLifetimeScope())
{
var processInstallers =
container.GetInstance<ServiceProcessInstaller>();
var serviceInstaller =
container.GetInstance<ServiceInstaller>();
Installers.Add(processInstallers);
Installers.Add(serviceInstaller);
}
}
}
By the why you don't need the LifetimeScope
at all in the installer, so you can write:
internal class InstallBootstrapper
{
public Container Build()
{
var container = new Container();
container.Register<ServiceProcessInstaller,
HelloServiceProcessInstaller>();
container.Register<ServiceInstaller,
GreetServiceInstaller>();
container.Register<IServiceNameProvider,
ServiceNameProvider>();
container.Verify();
return container;
}
}
[RunInstaller(true)]
public class ProjectInstaller : Installer
{
public ProjectInstaller()
{
var bootstrapper = new InstallBootstrapper();
var container = bootstrapper.Build();
var processInstallers =
container.GetInstance<ServiceProcessInstaller>();
var serviceInstaller =
container.GetInstance<ServiceInstaller>();
Installers.Add(processInstallers);
Installers.Add(serviceInstaller);
}
}
Upvotes: 2