0

I am trying to create a rest service in C# Web API.

At the moment I'm not considering any DB decisions, hence I'm adding a mock class library.

I'm creating a model interface and implementing the model in the mock class library.

public interface IUser
{
    int userId { get; set; }
    string firstName { get; set; }
    string lastName { get; set; }
    string email { get; set; }

    List<IUser> getAllUsers();
    IUser getUser(int ID);
    bool updateUser(IUser user);
    bool deleteUser(int ID);
}

and implementing this in the mock class library

public class User : IUser
{
    public string email { get; set; }
    public string firstName { get; set; }
    public string lastName { get; set; }
    public int userId { get; set; }

    public bool deleteUser(int ID)
    {
        throw new NotImplementedException();
    }

    public List<IUser> getAllUsers()
    {
        throw new NotImplementedException();
    }

    public IUser getUser(int ID)
    {
        throw new NotImplementedException();
    }

    public bool updateUser(IUser user)
    {
        throw new NotImplementedException();
    }
}

Now the mock library references the service application to implement the interface.

Now I need to call the mock implementation from the controller class in the service application.

How do I do that without creating a cyclic dependency. I did some research and came up with a solution that DI is the way to go.

Can someone help me to implement this with code samples?

Many thanks.

joeldroid
  • 155
  • 1
  • 9

3 Answers3

0

If you don't mind which IoC container you might use, I would recommend Ninject.

You need to install the next packages via Nuget:

Then in the Ninject configuration file NinjectWebCommon.cs in the end of RegisterServices() method add the following code:

kernel.Bind<IUser>().To<User>();

And now just add IUser as a parameter to the controller class and Ninject will automatically inject it.

public class MyController : Controller
{

private IUser _user;

     // Ninject will automatically inject a User instance here
     // on controller creation
     public MyController(IUser user)
     {
         _user = user;
     }
}

There are different approaches for using Ninject so you can search for other that will fit your needs better.

Ivan Yurchenko
  • 3,762
  • 1
  • 21
  • 35
0

"Now I need to call the mock implementation from the controller class in the service application."

This doesn't sound right. I think you have a design issue here; why do you need to reference a mock implementation of IUser from your service application?

  • One thing to bear in mind is that clients own the interface, so the IUser interface does not belong in the Mock class library at all; it should ideally be defined in a totally separate assembly so that both your mock class library and your service class library can reference it (and provide their own implementations for it if required).

  • This is the Dependency Inversion Principle and whilst I agree that a DI library of some kind can help you to manage the implementation of such Inversion of Control, I don't believe that it will help you here in the long run. You will probably still run into the same cyclic reference issues in the container itself.

  • Right now I think you first need to look at using the Stairway Pattern to get your Dependencies correctly inverted before you look at using any DI libraries

Community
  • 1
  • 1
Stephen Byrne
  • 7,400
  • 1
  • 31
  • 51
0

Now the mock library references the service application to implement the interface.

This is the source of your problem. I would recommend moving the interfaces for your data access layer out into a separate project. Then you can create a project with mock/in memory implementations, and later on add another project with the real implementations.

Another thing is that your IUser is the contract for your DTO (data transfer object), but it contains DAO (data access object) methods. Typically you would want to separate these concerns with something like the repository pattern.

public interface IUserRepository
{
    IEnumerable<IUser> GetAllUsers();
    IUser GetUser(int id);
    ...
}

This repository is what you would inject into your API controller.

Matt Cole
  • 2,491
  • 17
  • 21