Moq framework Func<T,T> - c#

I am new with Moq and TDD and what I am trying to do is to set up method on repository interface.
Here is full story.
I have a domain entity class called Tenant with property BusinessIdentificationNumber
public class Tenant:EntityBase<Tenant>,IAggregateRoot
{
...
public string BusinessIdentificationNumber {get;set;}
...
}
Next I have repository for this entity which interface is like
public interface IRepository<T>
{
...
T FindBy(Func<T,bool> func);
...
}
where the problem is, I use a domain service which holds the rules for creating a tenant and is like
public class TenantCreationService:ITenantCreationService
{
public TenantCreationService(IRepository<Tenant> tenantRepository){...}
public void CreateTenant(Tenant tenant)
{
//from here there is call to IRepository<Tenant>.FindBy(funcMethod);
}
}
And in unit testing where I am testing the TenantCreationService I mock the repository passed to constructor, but I would like to test the feature :
when tenant with BusinessIdentificationNumber already exists in storage or session it should be returned.
So I was trying to do it like
repositoryMock.Setup(x=>x.FindBy(It.Is<Tenant>(t=>t.BusinessIdentificationNumber
== _tenantInTest.BusinessIdentificationNumber))).Returns(_tenantInTest)
but it does not compile. You know what I want to do?
EDIT:
when i try to compile the snippet below
repositoryMock.Setup(e => e.FindBy(t => t.BusinessNumber == _validTenant.BusinessNumber)).Returns(
_validTenant);
i get exception
Unsupported expression: t => (t.BusinessNumber == value(DP.IPagac.UnitTests.DP.IPagac.Module.TenantManagement.TenantDomainServiceTests)._validTenant.BusinessNumber)

I think what you are trying the acheive is this (removed some things that were extraneous for example and created ITenent so it can be mocked dynamically):
[TestFixture]
public class Test
{
[Test]
public void CreateTenentAlreadyExistsTest()
{
var tenentMock = new Mock<ITenant>();
var repoMock = new Mock<IRepository<ITenant>>();
tenentMock.Setup(t => t.BusinessIdentificationNumber).Returns("aNumber");
repoMock.Setup(r => r.FindBy(It.Is<System.Func<ITenant, bool>>(func1 => func1.Invoke(tenentMock.Object)))).Returns(tenentMock.Object);
var tenantCreationService = new TenantCreationService(repoMock.Object);
tenantCreationService.CreateTenant(tenentMock.Object);
tenentMock.VerifyAll();
repoMock.VerifyAll();
}
}
public interface ITenant
{
string BusinessIdentificationNumber { get; set; }
}
public class Tenant : ITenant
{
public string BusinessIdentificationNumber { get; set; }
}
public interface IRepository<T>
{
T FindBy(System.Func<T, bool> func);
}
public class TenantCreationService : ITenantCreationService
{
private readonly IRepository<ITenant> _tenantRepository;
public TenantCreationService(IRepository<ITenant> tenantRepository)
{
_tenantRepository = tenantRepository;
}
public void CreateTenant(ITenant tenant)
{
var existingTenant =
_tenantRepository.FindBy(t => t.BusinessIdentificationNumber == tenant.BusinessIdentificationNumber);
if (existingTenant == null)
{
//do stuff
}
}
}
public interface ITenantCreationService
{
void CreateTenant(ITenant tenant);
}

"when tenant with BusinessIdentificationNumber already exists in storage or session it should be returned." - from this test description I understood that this behavior you should test in repository class not in on service class
In unit test for services you should not test data accesses layer I mean your repositories,
you should just verify that the repository method FindBy was called.
and my suggest Create ITenantRepositry that derive from IRepository interface and from base class Repostiry.

Related

How to get multiple implementations of the same service interface each in separate scopes

I have an asp.net core 2.2 web application. There is an Interface which is implemented by multiple classes.
services.AddTransient<IHandler, HandlerA>();
services.AddTransient<IHandler, HandlerB>();
Each implementation of IHandler injects scoped EF DbContext and if the same DbContext is shared between different threads, then periodically a floating exception will occur when trying to access the same entity. So I get each handler in a separate scope.
using (var scope = _serviceProvider.CreateScope())
{
var handlers = scope.ServiceProvider.GetServices<IHandler>();
await Task.WhenAll(handlers.Select(async h =>
{
using var internalScope = scope.ServiceProvider.CreateScope();
var handler = internalScope.ServiceProvider
.GetServices<IHandler>()
.First(f => f.Name == h.Name);
await handler.Handle(cancellationToken);
}));
}
This solution seems to work, but I'm not sure if it's optimal. Maybe there is a better way to get multiple implementations of the same service interface in separate scopes?
You do not need to access same entity using different DBContext.
Define services and inject in controllers explained above link. Each service will access DB using same db context through Manager Classes.
You can use service this way as you seeking best practices. And use dependency injection to access the services from controllers.
Define Service, Domain classes and interfaces.
public class Service : Attribute
{
}
//Domain Classes
public class Entity
{
string str {get; set;}
int numb {get; set;}
}
//DBContext
public class DbContext : IdentityDbContext
{
public DbContext(DbContextOptions<DbContext> options)
: base(options)
{
}
public DbSet<Entity> Entities { set; get; }
}
//Interfaces
interface IHandler
{
string method1(Entity entity);
int method2();
}
Implement Interfaces using manager classes
public class HandlerA: IHandler
{
private readonly DbContext _dbContext;
public HandlerA(DbContext dbContext)
{
_dbContext = dbContext;
}
string method1(Entity entity)
{
//access db or business stuff
_dbContext.Entities.Add(entity);
_dbContext.SaveChanges();
}
int method2(){}
}
public class HandlerB: IHandler
{
string method1(Entity entity)
{
//access db or business stuffs
_dbContext.Entities.Remove(entity);
_dbContext.SaveChanges();
}
int method2(){}
int method3(){}
}
//Services
[Service]
public class DoService1Stuff()
{
private readonly HandlerA _handlerA;
public DoService1Stuff(HandlerA handlerA)
{
_handlerA= handlerA;
}
//Implement your task
public Do(Entity entity)
{
_handlerA.method1(entity);
}
}
[Service]
public class DoService2Stuff()
{
private readonly HandlerB _handlerB;
public DoService2Stuff(HandlerB handlerB)
{
_handlerB= handlerB;
}
//Implement your task
public Do(Entity entity)
{
_handlerA.method1(entity);
}
}
Register services through dependency injection in startup.cs
services.AddTransient<IHandler, HandlerA>();
services.AddTransient<IHandler, HandlerB>();
Access services in controllers
[HttpPost]
public async Task<IActionResult> DoStuff1([FromServicec] DoService1Stuff doService1Stuff)
{
var entity= new Entity
{
str="hello",
numb=2020;
};
return Ok(doService1Stuff.Do(entity))
}
//Implement second service as needed.

Verifying function calls with anonymous functions in parameters

I have a class, a service, and two interfaces:
public class MyBasicObject
{
public MyBasicObject() { }
public int Id { get; set; }
public string Name { get; set; }
}
public interface ICacheProvider
{
T Get<T>(string key, Func<T> fetcher) where T:class;
}
public interface IMyBasicObjectRepository
{
MyBasicObject GetByName(string name);
}
public class MyBasicObjectService
{
public MyBasicObjectService(ICacheProvider cacheProvider,
IMyBasicObjectRepository repository)
{
CacheProvider = cacheProvider;
MyBasicObjectRepository = repository;
}
public ICacheProvider CacheProvider { get; set; }
public IMyBasicObjectRepository MyBasicObjectRepository { get; set; }
public MyBasicObject GetByName(string name)
{
return CacheProvider.Get<MyBasicObject>(name, () =>
MyBasicObjectRepository.GetByName(name));
}
}
Using RhinoMocks, I'd like to be able to verify that when MyBasicObjectService.GetByName("AnUniqueName") gets executed, so does CacheProvider.Get("AnUniqueName", () => MyBasicObjectRepository.GetByName("AnUniqueName")). I have a fixture set up like so:
[TestFixture]
public class MyBasicObjectServiceFixture
{
[Test]
public void GetByNameShouldCallCacheProviderFunction()
{
// Arrange
MockRepository mock = new MockRepository();
IMyBasicObjectRepository repo = mock.DynamicMock<IMyBasicObjectRepository>();
ICacheProvider cacheProvider = mock.DynamicMock<ICacheProvider>();
MyBasicObjectService service = new MyBasicObjectService(cacheProvider, repo);
cacheProvider.Expect(p => p.Get<MyBasicObject>("AnUniqueName", () => repo.GetByName("AnUniqueName")));
mock.ReplayAll();
// Act
var result = service.GetByName("AnUniqueName");
// Assert
mock.VerifyAll();
}
}
I would expect this test to pass, but when run, the assertion fails, notifying me that the function laid out in cacheProvider.Expect is not being called. Am I missing something reg. mocking out and testing methods that take parameters of Func<>?
Edit:
So if I do:
cacheProvider.Expect(p => p.Get<MyBasicObject>("AnUniqueName", () => repo.GetByName("AnUniqueName"))).IgnoreArguments();
(that is to say, add the IgnoreArguments() method onto the end of the expect call)
...the test passes just fine. I'm assuming, then, it's a problem with the argument passed in. Is there something I'm doing wrong in the expect where the cache provider method is getting called but it chokes on the anonymous method getting passed in?
The problem is that the two anonymous methods (the one in the Expect and the one which is created in GetByName are two different objects and therefor are not equal. You can fix that by partially matching the arguments like this:
cacheProvider.Expect(p => p.Get<MyBasicObject>(Arg<string>.Is.Equal("AnUniqueName"), Arg <Func<MyBasicObject>>.Is.NotNull));
What I ended up doing for the test was:
[TestFixture]
public class MyBasicObjectServiceFixture
{
[Test]
public void GetByNameShouldCallCacheProviderFunction()
{
// Arrange
MockRepository mock = new MockRepository();
IMyBasicObjectRepository repo = mock.DynamicMock<IMyBasicObjectRepository>();
ICacheProvider cacheProvider = mock.DynamicMock<ICacheProvider>();
MyBasicObjectService service = new MyBasicObjectService(cacheProvider, repo);
cacheProvider.Expect(p => p.Get<MyBasicObject>(Arg<string>.Is.Equal("AnUniqueName"), Arg<Func<MyBasicObject>>.Is.NotNull))
.WhenCalled(call =>
{
var repoCall = (Func<MyBasicObject>)call.Arguments[1];
repoCall.Invoke();
});
repo.Expect(c => c.GetByName("AnUniqueName"));
mock.ReplayAll();
// Act
var result = service.GetByName("AnUniqueName");
// Assert
mock.VerifyAll();
}
}
This works specifically for my use case (invoking a database retrieval in case of a cache miss, and making sure the service uses the correct repository call at that time), but is sort of a not-so-great work-around if you're not planning on invoking the anonymous function right away. I'm sure there are other alternatives with .WhenCalled, but for right now, this is working for me.

How mock a method with one parameter with moq

I'm not familiar with mocking. I'd like test if my method GetById return me an object User with an Id. Below the code, I'd like test if the GetById(10) return me an User with id = 10.
I set the moq (I hope it's correct) but how execute the moq ?
Thanks,
[TestMethod]
public void MyMoq()
{
var userMock = new Mock<IUsers>();
userMock.Setup(x => x.GetById(10)).Returns(new User());
//After ?
new Users().GetById(10);
}
public interface IUsers
{
IUser GetById();
}
public IUser GetById(int id)
{
using (var context = ....)
{
//code here
//return user here
}
}
Alright, as I said in comments, it's not clear for me what code you're trying to test. I see two options here.
1) The Users class implements IUsers interface and your intention is to test implementation of GetById(int) method.
In such case you do NOT need to mock the 'Users#GetById(id)' method, you just need to call it and check the result.
The code should look similar to:
interface IUser
{
int Id { get; }
}
class User : IUser
{
public int Id { get;set; }
}
interface IUsers
{
IUser GetById(int id);
}
class Users : IUser
{
public IUser GetById(int id)
{
// TODO: make call db call
// TODO: parse the result
// TODO: and return new User instance with all the data from db
return new User{ Id = id };
}
}
[TestMethod]
public void MyMoq()
{
// TODO: prepare/mock database. That's whole another story.
var users = new Users();
// act
var user = users.GetById(10);
// assert
Assert.AreEqual(10, user.Id);
}
2) Your Users#GetById(int) method is supposed to call the IUsers#GetById(int) and return the result. In such case you need to create mock of IUsers(as you've shown in question) and pass it to Users. The code should be(sorry for possible duplication):
interface IUser
{
int Id { get; }
}
class User : IUser
{
public int Id { get;set; }
}
interface IUsers
{
IUser GetById(int id);
}
class Users : IUser
{
private readonly IUser _users;
public Users(IUser users)
{
_users = users;
}
public IUser GetById(int id)
{
// next line of code is to be tested in unit test
return _users.GetById(id);
}
}
[TestMethod]
public void MyMoq()
{
var usersMock = new Mock<IUsers>();
usersMock.Setup(x => x.GetById(10)).Returns(new User());
var users = new Users(usersMock.Object);
// act
var user = users.GetById(10);
// assert
Assert.AreEqual(10, user.Id);
}
p.s. Could be useful to take a look at moq tutorial and The Art of Unit Testing book, Part 2 - Core techniques(page 47) - stubs, mocks, etc.
I don't quite sure what you want to test. You also has Mock class with some methods that you don't describe.
However, answering your question about mocking. Consider this class:
public class MyMoq : IUsers
{
private readonly Mock<IUsers> userMock;
public MyMoq(Mock<IUsers> userMock){
this.userMock = userMock;
}
[TestMethod]
public IUser GetById()
{
userMock.Setup(x => x.GetById(10)).Returns(new User());
//After ?
return new UsersDb().GetById(10);
}
}
To use it:
MyMoq moq = new MyMoq(new Mock<IUsers>());
User u = moq.GetById();
My assumption in this example is Mock<IUsers> is a repository and MyMoq is a service class. Also, IUser is an Entity Interface, and IUsers is a service interface.
To test userMock.Object should return the actual mocked IUsers object.
var userMock = new Mock<IUsers>();
userMock.Setup(x => x.GetById(10)).Returns(new User());
var mockobject = userMock.Object;
//Returns your mocked new User() instance
var newUserObject = mockobject.GetById(10);
In the above code, newUserObject has only created a new instance of User.
To test your GetById method, you need to call it again and Assert.
Assert.AreEqual(newUserObject.GetById(20).ID, 20); //Assume User has a property ID
Suggestion: It should be possible to have a better way to create the User instance.
GetById should be in it's own class (probably called Users) if that is what is being tested. Users could then accept a context in the constructor. Then mock this context to return stubbed data.
So in summary
Class Users implementing IUsers
Users has a constructor with parameter IContext (or whatever it would be called here)
Test class would mock IContext but not IUsers.
Call users.GetById and check the output is correct.
The way you would set up your context depends on what type of context it is, but see https://cuttingedge.it/blogs/steven/pivot/entry.php?id=84.

How to model this in DDD and repository pattern

I want to model service like this
public class FooService
{
public GetById(ISecurityContext context, id)
{
//checking context has right to view
//calling Foo repository to getById
}
public Add(ISecurityContext context,Foo fooEntity)
{
//checking context has right to add
//calling Foo repository to add
}
}
In the above methods i want to pass different type of SecurityContext
So what i have did is
Public Interface ISecurityContext
{
}
UsernamePasswordContext : ISecurityContext
{
public string Username { get; set; }
public string Password { get;set; }
}
SessionContext : ISecurityContext
{
public string SessionId {get ; set;}
}
So In my Account Service i have a method
public class AccountService
{
public Account GetAccountFromSecurityContext(ISecurityContext context)
{
if(context is UsernamePasswordContext)
return GetAccountByUsernamePassword(context.Username,context.Password);
else if (context is SessionContext)
return GetAccountBySessionId(context.SessionId);
// more else if for different type of context
}
}
In the above code i didnt liked so many if else
So i tried introducing polymorphism
So in my ISecurityContext interface i added a GetAccount method which all sub class will implement
Public Interface ISecurityContext
{
Account GetAccount();
}
UsernamePasswordContext : ISecurityContext
{
public string Username { get; set; }
public string Password { get;set; }
public Account GetAccount()
{
//call account service
GetAccountByUsernamePassword(this.Username,this.Password);
}
}
and my account service will become like this
public class AccountService
{
public Account GetAccountFromSecurityContext(ISecurityContext context)
{
context.GetAccount();
}
}
But the problem here is that i am calling a service/repository from my UsernamePasswordContext POCO which voilates DDD
So what are other ways i can model this scenario.
I think you're not far off from the solution. In this case, I would inject a factory into your AccountService that would take on the responsibility of the if..then..else. Then, the factory could use one of many possible solutions.
One change I would make right off is I would make your AccountService implement an interface which should make it easier to inject later. Assuming you're using some IOC container, you shouldn't have to worry too much about dependencies because you're letting the container handle all that.
Here are the pieces you already had, with some minor ajustments:
public class Account
{
//some account information and behavior
}
public interface ISecurityContext
{
}
public class UsernamePasswordContext : ISecurityContext
{
public string Username { get; set; }
public string Password { get; set; }
}
public class SessionContext : ISecurityContext
{
public string SessionId { get; set; }
}
Here's your account service along with it's implementation:
public interface IAccountService
{
Account GetAccountFromSecurityContext(ISecurityContext securityContext);
}
public class AccountService : IAccountService
{
readonly IAccountFactory _accountFactory;
public AccountService(IAccountFactory accountFactory)
{
_accountFactory = accountFactory;
}
public Account GetAccountFromSecurityContext(ISecurityContext securityContext)
{
Account account = _accountFactory.Create(securityContext);
return account;
}
}
So, you can see here that I've injected an IAccountFactory that will handle the actual creation (retrieval, whatever) of the Account object. All we care about at this point is that the account gets created/retrieved... we don't care about how.
There are a few ways you can implement a factory like this. One way is to use a type of strategy pattern where you have a list of widgets that know how to resolve an account. Then you just pick the widget (strategy) that matches and execute it. Something similar to this would be a factory that uses an IOC or service locator to resolve a type that has been registered previously in application configuration.
In the way of an example, here's one possible implementation of IAccountFactory using CommonServiceLocator:
public interface IAccountFactory
{
Account Create(ISecurityContext securityContext);
}
public class ServiceLocatorAccountFactory : IAccountFactory
{
readonly IServiceLocator _serviceLocator;
public ServiceLocatorAccountFactory(IServiceLocator serviceLocator)
{
_serviceLocator = serviceLocator;
}
public Account Create(ISecurityContext securityContext)
{
var resolverType = typeof (IAccountResolver<>).MakeGenericType(securityContext.GetType());
dynamic resolver = _serviceLocator.GetInstance(resolverType);
return resolver.Resolve(securityContext);
}
}
My factory here goes out to the service locator context and grabs whatever resolver matches our security context. Here are a couple examples of possible resolvers:
public interface IAccountResolver<in TSecurityContext> where TSecurityContext : ISecurityContext
{
Account Resolve(TSecurityContext securityContext);
}
public class UsernamePasswordAccountResolver : IAccountResolver<UsernamePasswordContext>
{
readonly IRepository _repository;
public UsernamePasswordAccountResolver(IRepository repository)
{
_repository = repository;
}
public Account Resolve(UsernamePasswordContext securityContext)
{
var account = _repository.GetByUsernameAndPassword(securityContext.Username,
securityContext.Password);
return account;
}
}
public class SessionAccountResolver : IAccountResolver<SessionContext>
{
public Account Resolve(SessionContext securityContext)
{
//get the account using the session information
return someAccount;
}
}
The only thing left is to register the resolvers in your IOC container so that they can be found when the service locator tries to resolve them in the factory.

MVC 3 - how to implement a service layer, do I need repositories?

I am currently building my first MVC 3 application, using EF Code First, SQL CE and Ninject.
I have read a lot about using Repositories, Unit of Work and Service Layers. I think I have got the basics sorted out, and I have made my own implementation.
This is my current setup:
Entities
public class Entity
{
public DateTime CreatedDate { get; set; }
public Entity()
{
CreatedDate = DateTime.Now;
}
}
public class Profile : Entity
{
[Key]
public Guid UserId { get; set; }
public string ProfileName { get; set; }
public virtual ICollection<Photo> Photos { get; set; }
public Profile()
{
Photos = new List<Photo>();
}
public class Photo : Entity
{
[Key]
public int Id { get; set; }
public Guid FileName { get; set; }
public string Description { get; set; }
public virtual Profile Profile { get; set; }
public Photo()
{
FileName = Guid.NewGuid();
}
}
SiteContext
public class SiteContext : DbContext
{
public DbSet<Profile> Profiles { get; set; }
public DbSet<Photo> Photos { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Interface: IServices
public interface IServices : IDisposable
{
PhotoService PhotoService { get; }
ProfileService ProfileService { get; }
void Save();
}
Implementation: Services
public class Services : IServices, IDisposable
{
private SiteContext _context = new SiteContext();
private PhotoService _photoService;
private ProfileService _profileService;
public PhotoService PhotoService
{
get
{
if (_photoService == null)
_photoService = new PhotoService(_context);
return _photoService;
}
}
public ProfileService ProfileService
{
get
{
if (_profileService == null)
_profileService = new ProfileService(_context);
return _profileService;
}
}
public void Save()
{
_context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
_context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Interface
public interface IPhotoService
{
IQueryable<Photo> GetAll { get; }
Photo GetById(int photoId);
Guid AddPhoto(Guid profileId);
}
Implementation
public class PhotoService : IPhotoService
{
private SiteContext _siteContext;
public PhotoService(SiteContext siteContext)
{
_siteContext = siteContext;
}
public IQueryable<Photo> GetAll
{
get
{
return _siteContext.Photos;
}
}
public Photo GetById(int photoId)
{
return _siteContext.Photos.FirstOrDefault(p => p.Id == photoId);
}
public Guid AddPhoto(Guid profileId)
{
Photo photo = new Photo();
Profile profile = _siteContext.Profiles.FirstOrDefault(p => p.UserId == profileId);
photo.Profile = profile;
_siteContext.Photos.Add(photo);
return photo.FileName;
}
}
Global.asax
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
Database.SetInitializer<SiteContext>(new SiteInitializer());
}
NinjectControllerFactory
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel ninjectKernel;
public NinjectControllerFactory()
{
ninjectKernel = new StandardKernel();
AddBindings();
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return controllerType == null
? null
: (IController)ninjectKernel.Get(controllerType);
}
private void AddBindings()
{
ninjectKernel.Bind<IServices>().To<Services>();
}
}
PhotoController
public class PhotoController : Controller
{
private IServices _services;
public PhotoController(IServices services)
{
_services = services;
}
public ActionResult Show(int photoId)
{
Photo photo = _services.PhotoService.GetById(photoId);
if (photo != null)
{
string currentProfile = "Profile1";
_services.PhotoService.AddHit(photo, currentProfile);
_services.Save();
return View(photo);
}
else
{
// Add error message to layout
TempData["message"] = "Photo not found!";
return RedirectToAction("List");
}
}
protected override void Dispose(bool disposing)
{
_services.Dispose();
base.Dispose(disposing);
}
}
I can build my solution and it seems to be working correctly.
My questions are:
Are there any obvious flaws in my implementation that I am missing?
Will I be able to use this with TDD? Usually I see mocking of repositories but I haven't used that in the above, will that cause issues?
Am I using DI (Ninject) correctly and enough?
I am a hobby programmer, so any comments and/or suggestions to my code are welcome!
You've got the general idea, but it takes a while to really get used to Dependency Injection. I see a number of possible improvements to be made:
Your IServices interface seems unnecessary. I'd prefer to have the controller specify which services it needs (IPhotoService, etc.) via its constructor, rather than using the IServices interface like some kind of strongly-typed service locator.
Did I see a DateTime.Now in there? How are you going to verify that the date gets set correctly in a unit test? What if you decide to support multiple time zones later? How about using an injected date service to produce that CreatedDate?
There is a very good Ninject extension specifically for MVC. It takes care of plugging into the various points that MVC 3 supports for injection. It implements things like your NinjectControllerFactory. All you have to do is make your Global class extend a specific Ninject-based application.
I'd suggest using NinjectModules for setting your bindings, rather than setting them in your ControllerFactory.
Consider using Binding by Convention so that you don't have to explicitly bind each service to its implementation.
Update
The Ninject MVC Extension can be found here. See the README section for an example of how to extend the NinjectHttpApplication. This example uses Modules, which you can read more about here. (They're basically just a place to put your binding code so that you don't violate the Single Responsibility Principle.)
Regarding conventions-based bindings, the general idea is to have your binding code scan the appropriate assemblies and automatically bind things like IPhotoService to PhotoService based on the naming convention. There is another extension here to help with such things. With it, you can put code like this in your module:
Kernel.Scan(s =>
{
s.From(assembly);
s.BindWithDefaultConventions();
});
The above code will auto-bind every class in the given assembly to any interface it implements that follows the "Default" conventions (e.g. Bind<IPhotoService>().To<PhotoService>()).
Update 2
Regarding using the same DbContext for an entire request, you can do something like this (using the Ninject.Web.Common library, which is required by the MVC extension):
Bind<SiteContext>().ToSelf().InRequestScope();
Then any context-dependent services that Ninject creates will share the same instance across a request. Note that I have personally used shorter-lived contexts, so I don't know off the top of my head how you'd force the context to be disposed at the end of the request, but I'm sure it wouldn't be too difficult.
The IServices and Services types seem superfluous to me. If you drop them and change your controller's constructor to be
public PhotoController(IPhotoService photoService, IProfileService profileService)
{
_photoService = photoService;
_profileService = profileService;
}
it will be more apparent what it is actually depending on. Moreover, when you create a new controller, that only really needs IProfileService, you can just pass an IProfileService instead of a full IService, thus giving the new controller a lighter dependency.
I could argue that your services look very much with a repository. Look closely to the interface:
IQueryable<Photo> GetAll { get; }
Photo GetById(int photoId);
Guid AddPhoto(Guid profileId);
Looks very much like a repository to me. Maybe because the example is rather simple but I see the point of having a service if you add use case logic on it. instead of these rather simpel CRUD operations.
And you could argue that EFs DbSet and DbContext are the repositories and unit of work of the app...and at this point we enter a new zone that is somewhat out of scope of the question.

Categories

Resources