Beats
Beats

Reputation: 201

Converting Autofac to Simple Injector

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

Answers (1)

nemesv
nemesv

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

Related Questions