-1

I have an MVC application that uses Entity Framework. I am using a repository, unit of work and unity as dependency injection.

The problem I have is that I have different authentication types, and each type I want a different class, so I decided to use the Strategy pattern

    public interface IAuthStrategy
    {
        OperationResponse<AuthenticationMechanismDTO> GetAuthenticationMechanism(string userName);
    }

    public class AuthStrategy 
    {
        readonly IAuthStrategy _authStrategy;

        public AuthStrategy(IAuthStrategy authStrategy)
        {
            this._authStrategy = authStrategy;
        }

        public OperationResponse<AuthenticationMechanismDTO> GetAuthenticationMechanism(string userName)
        {
            return _authStrategy.GetAuthenticationMechanism(userName);

        }

    }



    public class UserNamePasswordMechanism : IAuthStrategy
    {

        private IInstitutionRepository _institutionRepository;

        public UserNamePasswordMechanism(IInstitutionRepository institutionRepository)
        {
            this._institutionRepository = institutionRepository;
        }

        public OperationResponse<AuthenticationMechanismDTO> GetAuthenticationMechanism(string userName)
        {

            throw new NotImplementedException();
        }
    }

My problem is that I am injecting IAuthStrategy into the controller, and it gives me an error, because instead of implementing IAuthStrategy, I am passing that to AuthStrategy constructor, as you can see that in my code.

How can I fix this error?

Here is my controller

 public class EmployeeController : ApiController
        {

            private IAuthStrategy _auth;

            public EmployeeController(IAuthStrategy auth)
            {
                this._employeeBL = employeeBL;
                this._auth = auth;

            }}
    }

Here is unity config where i am registering my types

public class UnityConfig
    {
        #region Unity Container
        private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
        {
            var container = new UnityContainer();
            RegisterTypes(container);
            return container;
        });

        /// <summary>
        /// Gets the configured Unity container.
        /// </summary>
        public static IUnityContainer GetConfiguredContainer()
        {
            return container.Value;
        }
        #endregion

        /// <summary>Registers the type mappings with the Unity container.</summary>
        /// <param name="container">The unity container to configure.</param>
        /// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to 
        /// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>


   public static void RegisterTypes(IUnityContainer container)
    {
        // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
        // container.LoadConfiguration();

        // TODO: Register your types here

        container.RegisterType<IInstitutionRepository, InstitutionRepository>();

        container.RegisterType<IAuthStrategy, AuthStrategy>();

        GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);

    }
}
Brendan Green
  • 11,676
  • 5
  • 44
  • 76
BraveBoy
  • 117
  • 1
  • 14
  • Ok - you are going to need to provide some additional context to your problem. Can you please show us how you are registering your classes via Unity, show your controller that you are passing `IAuthStrategy` into, and the exact error message that you are getting. – Brendan Green May 27 '15 at 22:17
  • 1
    How about the error? Just saying that you get an error, without detailing what the actual error was, makes it hard to help. – Brendan Green May 27 '15 at 23:25
  • here is error: Error 1 The type 'HRBL.AuthStrategy' cannot be used as type parameter 'TTo' in the generic type or method 'Microsoft.Practices.Unity.UnityContainerExtensions.RegisterType(Microsoft.Practices.Unity.IUnityContainer, params Microsoft.Practices.Unity.InjectionMember[])'. There is no implicit reference conversion from 'HRBL.AuthStrategy' to 'HRBL.IAuthStrategy'. C:\Farhan\Angular\SogetiEmployees\SogetiEmployees\App_Start\UnityConfig.cs 49 13 SogetiEmployees – BraveBoy May 28 '15 at 00:52
  • That's because you are asking unity to register `AuthStrategy` as an `IAuthStrategy`, when it doesn't implement the interface. If you want to use an instance of `AuthStrategy` passed into the controller to then ask it for the `IAuthStrategy` to use at runtime, you'll need another interface and register that instead. – Brendan Green May 28 '15 at 01:07
  • that i know, Can you tell me the solution? – BraveBoy May 28 '15 at 01:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/78962/discussion-between-braveboy-and-brendan-green). – BraveBoy May 28 '15 at 01:11

2 Answers2

1

Your unit registrations and classes look a little off.

From what I can gather, this is what you really want to do.

Setup a factory that will determine at runtime which IAuthStrategy should be used:

public interface IAuthStrategyFactory
{
    IAuthStrategy GetAuthStrategy();
}

public class AuthStrategyFactory : IAuthStrategyFactory
{
    readonly IAuthStrategy _authStrategy;

    public AuthStrategy(...)
    {
        //determine the concrete implementation of IAuthStrategy that you need
        //This might be injected as well by passing 
        //in an IAuthStrategy and registering the correct one via unity  at startup.
        _authStrategy = SomeCallToDetermineWhichOne(); 
    }

    public IAuthStrategy GetAuthStrategy() 
    {
        return _authStrategy;
    }
}

This is your existing AuthStrategy:

public interface IAuthStrategy
{
    OperationResponse<AuthenticationMechanismDTO> GetAuthenticationMechanism(string userName);
}

public class UserNamePasswordMechanism : IAuthStrategy
{

    private IInstitutionRepository _institutionRepository;

    public UserNamePasswordMechanism(IInstitutionRepository institutionRepository)
    {
        this._institutionRepository = institutionRepository;
    }

    public OperationResponse<AuthenticationMechanismDTO> GetAuthenticationMechanism(string userName)
    {

        throw new NotImplementedException();
    }
}

Register the factory with unity:

container.RegisterType<IAuthStrategyFactory, AuthStrategyFactory>();

In your controller:

public class EmployeeController : ApiController
{
    private IAuthStrategy _auth;

    public EmployeeController(IAuthStrategyFactory authFactory)
    {
        this._employeeBL = employeeBL;
        this._auth = authFactory.GetAuthStrategy();
    }
}
Dirty Coder
  • 114
  • 2
  • 12
Brendan Green
  • 11,676
  • 5
  • 44
  • 76
  • public class EmployeeController : ApiController { private IAuthStrategy _auth; public EmployeeController(IEmployeeBL employeeBL, IAuthStrategyFactory auth) { this._auth = auth.GetAuthStrategy(); }} container.RegisterType(); – BraveBoy May 28 '15 at 02:44
  • Thanks Brendan for help i fixed that issue, but i am facing one more issue, Now i added on more calss which is implementing IAuthStrategy now issue is unity is resolving that but always executing new class which i just implemented, If you are ok i can share that code as well for more understanding. – BraveBoy May 29 '15 at 15:55
0

Actually i missed implemented IAuthStrategyFactory on AuthStrategyFactory, once i implemented and register in unity container that worked.

Thanks

BraveBoy
  • 117
  • 1
  • 14