How do I inject a class using extension methods? ASP.NET Identity

I am trying to inject into my controller ApplicationUserManager from Identity ASP.NET. This is the class I'm trying to inject:

public class ApplicationUserManager : UserManager<ApplicationUser>, IApplicationUserManager
    { ... }

      

This is how I am trying to inject into the controller:

        private readonly IApplicationUserManager _userManager;

        public MyController(IApplicationUserManager userManager)
        {
            _userManager = userManager;
        }

      

The thing is, when I try to get methods from _userManager when I write _userManager.

intellisense gives me only Async methods. For example, _userManager.RemoveFromRoleAsync()

instead of _userManager.RemoveFromRole()

. This is because my interface only has asynchronous methods. But the Synchronize (not Async) methods are extension methods for the UserManager.

public static class UserManagerExtensions
    { ...
    public static IdentityResult RemoveFromRole<TUser, TKey>(this UserManager<TUser, TKey> manager, TKey userId,
                string role)
                where TKey : IEquatable<TKey>
                where TUser : class, IUser<TKey>
            {
                if (manager == null)
                {
                    throw new ArgumentNullException("manager");
                }
                return AsyncHelper.RunSync(() => manager.RemoveFromRoleAsync(userId, role));
            }
        ...}

      

UserManager also comes from another class:

public class UserManager<TUser> : UserManager<TUser, string> where TUser : class, IUser<string>
    {
     ...
     }

      

Question: How do I get the sync methods in my controller?

+3


source to share


2 answers


Since extension methods are applied to the class definition and not the interface, you will also need to drop the IApplicationUserManager in the UserManager in the first place. Unfortunately, this is not a very good practice from a DI and a mocking point of view. To illustrate this, this should work ...

if (IApplicationUserManager is UserManager)
{
    UserManager userManager = (UserManager)IApplicationUserManager ;
    userManager.RemoveFromRole(...)
}

      



But I do not recommend this as the controller should not have implementation knowledge and that is your problem. The point is that an extension method by its nature is defined only for the implementation of a class, the interface does not know about it.

So it might actually be better to place the functionality of an extension method in a method declared on an interface.

0


source


DI does not require an interface, it requires an abstraction. Since your implementation is a subclass, you can say your abstraction is UserManager<ApplicationUser>

. It also means that another implementation is acceptable UserManager<ApplicationUser>

.

public class ApplicationUserManager : UserManager<ApplicationUser>
{ ... }

private readonly UserManager<ApplicationUser> _userManager;

public MyController(UserManager<ApplicationUser> userManager)
{
    _userManager = userManager;
}

      

Now, if your controller depends on additional members of what is currently IApplicationUserManager

(and I would expect so), you need to make those members an abstract base class so that it can be injected into your controller so it can inherit as well UserManager<ApplicationUser>

.



public class ApplicationUserManager : ApplicationUserManagerBase
{ ... }

public abstract class ApplicationUserManagerBase : UserManager<ApplicationUser>
{ ... }

private readonly ApplicationUserManagerBase _userManager;

public MyController(ApplicationUserManagerBase userManager)
{
    _userManager = userManager;
}

      

To do the implementation or layout you just need to inherit ApplicationUserManagerBase

. It's better than casting because the implementation is loosely coupled with abstraction.

Oh, and back to the original problem - all extension methods UserManager<TUser, TKey>

will be available at ApplicationUserManager

if you follow this approach. A big hint is to define an extension method: this UserManager<TUser, TKey> manager

- you must define an abstraction that includes that abstraction for it to work.

0


source







All Articles