dependency-injectionninjectinversion-of-controllight-inject

dependency injection - convert ninject di to lightinject di


How do I convert the following Ninject DI to the equivalent for LightInject DI? I'm having issues with getting to the right syntax.

Database.SetInitializer(new MigrateDatabaseToLatestVersion<DefaultMembershipRebootDatabase, BrockAllen.MembershipReboot.Ef.Migrations.Configuration>());

kernel.Bind<UserAccountService>().ToSelf();
kernel.Bind<AuthenticationService>().To<SamAuthenticationService>();
kernel.Bind<IUserAccountQuery>().To<DefaultUserAccountRepository>().InRequestScope();
kernel.Bind<IUserAccountRepository>().To<DefaultUserAccountRepository>().InRequestScope();

On my original question, I didn't include this, but this (also posted as comment to this post) was the not working code I attempted to make it work:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<DefaultMembershipRebootDatabase, BrockAllen.MembershipReboot.Ef.Migrations.Configuration>());

container.Register<UserAccountService>();
container.Register<AuthenticationService, SamAuthenticationService>();
container.Register<IUserAccountQuery, DefaultUserAccountRepository>(new PerRequestLifeTime());
container.Register<IUserAccountRepository, DefaultUserAccountRepository>(new PerRequestLifeTime());

The error message (without the stack trace) given was this:

Exception Details: System.InvalidOperationException: Unresolved dependency [Target Type: BrockAllen.MembershipReboot.Ef.DefaultUserAccountRepository], [Parameter: ctx(BrockAllen.MembershipReboot.Ef.DefaultMembershipRebootDatabase)], [Requested dependency: ServiceType:BrockAllen.MembershipReboot.Ef.DefaultMembershipRebootDatabase, ServiceName:]

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

*If anyone wants to see the stack trace too - * just ask, and I'll post it in a reply to this question.

The constructor for DefaultMembershipRebootDatabase (as was in a sample project, my project used the dll provided through nuget, and the constructor wasn't available, but I'm pretty sure they're more than likely the same in both cases (seeing as how it comes from the same source...) is:

public class DefaultMembershipRebootDatabase : MembershipRebootDbContext<RelationalUserAccount>
{
    public DefaultMembershipRebootDatabase()
        : base()
    {
    }

    public DefaultMembershipRebootDatabase(string nameOrConnectionString)
        : base(nameOrConnectionString)
    {
    }

    public DefaultMembershipRebootDatabase(string nameOrConnectionString, string schemaName)
        : base(nameOrConnectionString, schemaName)
    {
    }
}

This is the constructor (as was in the same aforementioned sample project) for the DefaultUserAccountRepository:

public class DefaultUserAccountRepository
       : DbContextUserAccountRepository<DefaultMembershipRebootDatabase, RelationalUserAccount>, 
         IUserAccountRepository
{
    public DefaultUserAccountRepository(DefaultMembershipRebootDatabase ctx)
        : base(ctx)
    {
    }

    IUserAccountRepository<RelationalUserAccount> This { get { return (IUserAccountRepository<RelationalUserAccount>)this; } }

    public new UserAccount Create()
    {
        return This.Create();
    }

    public void Add(UserAccount item)
    {
        This.Add((RelationalUserAccount)item);
    }

    public void Remove(UserAccount item)
    {
        This.Remove((RelationalUserAccount)item);
    }

    public void Update(UserAccount item)
    {
        This.Update((RelationalUserAccount)item);
    }

    public new UserAccount GetByID(System.Guid id)
    {
        return This.GetByID(id);
    }

    public new UserAccount GetByUsername(string username)
    {
        return This.GetByUsername(username);
    }

    UserAccount IUserAccountRepository<UserAccount>.GetByUsername(string tenant, string username)
    {
        return This.GetByUsername(tenant, username);
    }

    public new UserAccount GetByEmail(string tenant, string email)
    {
        return This.GetByEmail(tenant, email);
    }

    public new UserAccount GetByMobilePhone(string tenant, string phone)
    {
        return This.GetByMobilePhone(tenant, phone);
    }

    public new UserAccount GetByVerificationKey(string key)
    {
        return This.GetByVerificationKey(key);
    }

    public new UserAccount GetByLinkedAccount(string tenant, string provider, string id)
    {
        return This.GetByLinkedAccount(tenant, provider, id);
    }

    public new UserAccount GetByCertificate(string tenant, string thumbprint)
    {
        return This.GetByCertificate(tenant, thumbprint);
    }
}

And this is the controller in my project:

namespace brockallen_MembershipReboot.Controllers
{
using System.ComponentModel.DataAnnotations;

using BrockAllen.MembershipReboot;
using BrockAllen.MembershipReboot.Mvc.Areas.UserAccount.Models;

public class UserAccountController : Controller
{
    UserAccountService _userAccountService;
    AuthenticationService _authService;

    public UserAccountController(AuthenticationService authService)
    {
        _userAccountService = authService.UserAccountService;
        _authService = authService;
    }

    // GET: /UserAccount/
    [Authorize]
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Login()
    {
        return View(new LoginInputModel());
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Login(LoginInputModel model)
    {
        if (ModelState.IsValid)
        {
            /*BrockAllen.MembershipReboot.*/UserAccount account;
            if (_userAccountService.AuthenticateWithUsernameOrEmail(model.Username, model.Password, out account))
            {
                _authService.SignIn(account, model.RememberMe);

                _authService.SignIn(account, model.RememberMe);

                /*if (account.RequiresTwoFactorAuthCodeToSignIn())
                {
                    return RedirectToAction("TwoFactorAuthCodeLogin");
                }
                if (account.RequiresTwoFactorCertificateToSignIn())
                {
                    return RedirectToAction("CertificateLogin");
                }

                if (_userAccountService.IsPasswordExpired(account))
                {
                    return RedirectToAction("Index", "ChangePassword");
                }*/

                if (Url.IsLocalUrl(model.ReturnUrl))
                {
                    return Redirect(model.ReturnUrl);
                }

                return RedirectToAction("Index");
            }
            else
            {
                ModelState.AddModelError("", "Invalid Username or Password");
            }
        }

        return View(model);
    }

    public ActionResult Register()
    {
        return View(new RegisterInputModel());
    }

    [ValidateAntiForgeryToken]
    [HttpPost]
    public ActionResult Register(RegisterInputModel model)
    {
        if (ModelState.IsValid)
        {
            try
            {
                var account = _userAccountService.CreateAccount(model.Username, model.Password, model.Email);
                ViewData["RequireAccountVerification"] = _userAccountService.Configuration.RequireAccountVerification;
                return View("Success", model);
            }
            catch (ValidationException ex)
            {
                ModelState.AddModelError("", ex.Message);
            }
        }
        return View(model);
    }
}
}

The constructor for AuthenicationService is:

public abstract class AuthenticationService : AuthenticationService<UserAccount>
{
    public new UserAccountService UserAccountService
    {
        get { return (UserAccountService)base.UserAccountService; }
        set { base.UserAccountService = value; }
    }

    public AuthenticationService(UserAccountService userService)
        : this(userService, null)
    {
    }

    public AuthenticationService(UserAccountService userService, ClaimsAuthenticationManager claimsAuthenticationManager)
        : base(userService, claimsAuthenticationManager)
    {
    }
}

Solution

  • By default, LightInject does not resolve concrete classes without registering them, while NInject does.

    For example, NInject can resolve DefaultMembershipRebootDatabase without registering it, while LightInject cannot by default. Take a look at this.

    In any way, to fix your issue, make sure that you register your concrete classes (that are needed as dependencies in other classes). Here is an example:

    container.Register<DefaultMembershipRebootDatabase>();
    

    I am assuming here that some class has a dependency on the concrete class DefaultMembershipRebootDatabase. If you have other concrete class dependencies, make sure that you also register them.