Inject Interface to Overloaded Class Constructor Using StructureMap - c#

I'm using StructureMap in ASP .Net MVC 4 and I have got the following Interface and implemented class in my project infrastructure :
public interface IUnitOfWork
{
void Commit();
}
public class UnitOfWork : IUnitOfWork
{
public void Commit()
{
// Track all changes in database
}
}
My HomeController is used the IUnitOfWork interface as constructor parameter :
public class HomeController
{
IUnitOfwork unitOfWork;
public HomeController(IUnitOfwork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
}
How can I inject IUniOfWork interface to overloaded HomeController class as parameter?

You must perform the following steps:
Remove and uninstall any configurations and packages for StructureMap.
Install structurmap.mvc4 from nuget
Configure your IoC container as :
x.For(IUnitOfWork).Use(UnitOfWork)

Related

Failed to call service from aspnetboilerplate asp.net-core project controller

Work on Aspnet core boilerplate framework stuck on one issue, form my controller failed to call services.
Application class library contains IEmployeeService and EmployeeService, how to call them from my EmployeeController.
Service
public interface IEmployeeService
{
int CreateEmployee(CreateEmployeeDto data);
IEnumerable<EmployeeListDto> GetEmployeeList();
}
public class EmployeeService : IEmployeeService
{
}
Controller
[AbpMvcAuthorize]
public class EmployeeController : HRISControllerBase
{
private readonly IEmployeeService _employeeService;
public EmployeeController(
IEmployeeService employeeService
)
{
_employeeService = employeeService;
}
public ActionResult Index()
{
return View();
}
}
Note: Do project need to configure something in ConfigureServices on the Startup.cs file.
You need register it in the ConfigureServices method:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IEmployeeService, EmployeeService>();
}
Implement ITransientDependency.
public class EmployeeService : IEmployeeService, ITransientDependency
{
// ...
}
From https://aspnetboilerplate.com/Pages/Documents/Dependency-Injection#helper-interfaces:
ASP.NET Boilerplate provides the ITransientDependency, the IPerWebRequestDependency and the ISingletonDependency interfaces as a shortcut.
You can use registered your class in Startup.cs class.here asp..net core provide inbuild DI.
According to the docs
"ASP.NET Boilerplate automatically registers all Repositories, Domain Services, Application Services"
As such all you should need to do is change your IEmployeeService to inherit from IApplicationService:
public interface IEmployeeService : IApplicationService
{
int CreateEmployee(CreateEmployeeDto data);
IEnumerable<EmployeeListDto> GetEmployeeList();
}

No service for type 'MyType' has been registered

I have a generic repository architecture that looks like this:
Repository
public interface IRepository<T> where T: class
{
IList<T> Get(Func<T, bool> where);
}
public abstract class Repository<T> : IRepository<T> where T: class
{
private readonly DbSet<T> _entity;
protected Repository(ApplicationDbContext dbContext)
{
_entity = dbContext.Set<T>();
}
public IList<T> Get(Func<T, bool> where)
{
return _entity.Where(where).ToList();
}
}
Then concrete implementations are created like this:
UserRepository
public class UserRepository : Repository<ApplicationUser>
{
public UserRepository(ApplicationDbContext dbContext) : base(dbContext) {}
// Can add any other methods I want that aren't included in IRepository
}
I'll likely have quite a few services, so rather than having each one passed into the controller individually, I thought I'd try passing in a single factory that can produce repositories for me.
RepositoryFactory
public interface IRepositoryFactory
{
T GetRepository<T>() where T : class;
}
public class RepositoryFactory : IRepositoryFactory
{
private readonly IServiceProvider _provider;
public RepositoryFactory(IServiceProvider serviceProvider)
{
_provider = serviceProvider;
}
public T GetRepository<T>() where T : class
{
return _provider.GetRequiredService<T>(); // ERROR: No service for type 'UserRepository' has been registered
}
}
Now, in setting up dependency injection, I registered the services like this:
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// [...]
services.AddScoped<IRepository<ApplicationUser>, UserRepository>();
services.AddScoped<IRepositoryFactory, RepositoryFactory>();
// [...]
}
This is all used in the controller like this:
Controller
public class HomeController : Controller
{
private readonly UserRepository _userRepository;
public HomeController(IRepositoryFactory repositoryFactory)
{
_userRepository = repositoryFactory.GetRepository<UserRepository>(); // ERROR: No service for type 'UserRepository' has been registered
}
// [...]
}
When I call _provider.GetRequiredService<T>() in the repositoryFactory.GetRepository<UserRepository>() method, I get the error in the comment above.
The RepositoryFactory is coming through just fine, but the UserRepository isn't getting registered. What am I missing? I've tried calling the GetRepository method outside of the constructor, and I've tried change AddScoped to the other Add variants (Transient and Singleton), but to no avail.
You are taking dependency on UserRepository, which is implementation and not interface, that's not good (given that you actually have that interface registered in container). Instead you need to take dependency on interface: IRepository<ApplicationUser>. So change your factory interface:
public interface IRepositoryFactory
{
IRepository<T> GetRepository<T>() where T : class;
}
Implementation:
public IRepository<T> GetRepository<T>() where T : class
{
return _provider.GetRequiredService<IRepository<T>>(); // ERROR: No service for type 'UserRepository' has been registered
}
And controller:
public class HomeController : Controller
{
private readonly IRepository<ApplicationUser> _userRepository;
public HomeController(IRepositoryFactory repositoryFactory)
{
_userRepository = repositoryFactory.GetRepository<ApplicationUser>(); // ERROR: No service for type 'UserRepository' has been registered
}
// [...]
}
Now it doesn't work, because you registered IRepository<ApplicationUser> in container (with implementation being UserRepository), but UserRepository which you are trying to resolve is not registered (and as said above - you should not resolve it anyway).
Looks like my problem had to do with my understanding of AddScoped. Looking at the docs, the two type parameters in AddScoped are TService and TImplementation. So in my Startup class above, the SERVICE I'm registering is IRepository<ApplicationUser>, not ApplicationRepository. The IMPLEMENTATION I'm registering is ApplicationRepository.
To fix this, I changed my Startup class to say that UserRepository is the service being registered.
public void ConfigureServices(IServiceCollection services)
{
// [...]
// OLD: services.AddScoped<IRepository<ApplicationUser>, UserRepository>();
services.AddScoped<UserRepository>();
services.AddScoped<IRepositoryFactory, RepositoryFactory>();
// [...]
}
But this approach relies on an implementation rather than an abstraction (interface), so I took it a step further and introduced an interface for the UserRepository class and registered that in Startup.
UserRepository
public interface IUserRepository : IRepository<ApplicationUser>
{
void DoTheThing();
}
public class UserRepository : Repository<ApplicationUser>, IUserRepository
{
public UserRepository(ApplicationDbContext dbContext) : base(dbContext) {}
public void DoTheThing()
{
}
}
Startup
public void ConfigureServices(IServiceCollection services)
{
// [...]
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<IRepositoryFactory, RepositoryFactory>();
// [...]
}

Use DI in Data Access Layer with ApplicationDbContext (netcore 2.0)

I have some problem with DI (Dependancy Injection). My project is on netcore 2.0 and has few layers (standard N-Tier Architecture). I'm trying to move EF Core 2 from Presentation Layer to Data Access Layer and I have created the following classes in DAL:
namespace MyProject.Infrastructure.Implementation.MySql.Contexts
{
public class ApplicationDbContext : DbContext
{
private readonly IConfiguration _configuration;
public ApplicationDbContext(IConfiguration configuration)
{
_configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseMySql(
Configuration.GetConnectionString("MySql")
);
}
public DbSet<Test> Test { get; set; }
}
}
Then I prepared base class for all DAL engines:
namespace MyProject.Infrastructure.Implementation.MySql
{
public class BaseEngine : IBaseEngine
{
private readonly ApplicationDbContext _context;
protected ApplicationDbContext Db => _context;
public BaseEngine(ApplicationDbContext context)
{
_context = context;
}
}
}
So, my common engine should look like this:
namespace MyProject.Infrastructure.Implementation.MySql
{
public class TestEngine : BaseEngine
{
public List<Test> GetTestList()
{
return Db.Test.ToList();
}
}
}
The problem is that I get error, BaseEngine needs parameter to be passed in constructor and I don't want to create all instances manually, I need somehow use Dependancy Injection that automatically creates instances of ApplicationDbContext and IConfiguration when BaseEngine and ApplicationDbContext will be created..
Any ideas?
Create a public interface for ApplicationDbContext, like IApplicationDbContext. Put that in the constructor for BaseEngine instead of the concrete class. Make the BaseEngine constructor protected. The BaseEngine constructor should look like:
protected BaseEngine(IApplicationDbContext context)
Then, since TestEngine is derived from BaseEngine, and BaseEngine requires a constructor argument, you have to pass that in from the TestEngine constructor like:
public TestEngine(IApplicationDbContext context) : base(context)

Pass DbContext object as parameter through autofac class register

I have a 2 tier architecture application(Web and Service) in MVC. I have registered my service classes in the startup method in web project like below,
protected void Application_Start()
{
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterControllers(typeof(MvcApplication).Assembly);
containerBuilder.RegisterModelBinders(Assembly.GetExecutingAssembly());
containerBuilder.RegisterModelBinderProvider();
containerBuilder.RegisterType<SearchService>().As<ISearchService>();
var container = containerBuilder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
I have created a DbContext with interface, like below
public interface IApplicationDbContext
{
DbSet<Customer> Customers { get; set; }
}
and I have a DbContextClass like this,
public class ApplicationDbContext :
IdentityDbContext<User, Role, Guid, UserLogin, UserRole, UserClaim>,
IApplicationDbContext
{
public ApplicationDbContext() : base("DefaultConnection")
{
Database.SetInitializer(new CreateDatabaseIfNotExists<ApplicationDbContext>());
}
}
Here my question is, I want to pass DbContext object as parameter to below service class, like this
public class SearchService : ISearchService
{
IApplicationDbContext _dbContext;
public QueueService(IApplicationDbContext context)
{
_dbContext = context;
}
}
I think you use SearchService in your MVC Controller, so u have to create ISearchService instance there. In this case Autofac can make constructor injection in you controller.
public class ExampleController : Controller
{
ISearchService _svc;
public B2BHealthApiController(ISearchService s)
{
_svc = s;
}
}
When Autofac creates instance of ISearchService, engine defines that ISearchService require instance of IApplicationDbContext and creates it automaticly (the same constructor injection).
So you just have to say Autofac where take IApplicationDbContext and ISearchService instances. Add to your Application_Start
builder.RegisterType<ApplicationDbContext>()
.As<IApplicationDbContext>()
.InstancePerDependency();
builder.RegisterType<SearchService>()
.As<ISearchService>()
.InstancePerRequest();

How to inject the same instance of a class with Ninject?

I am using Ninject for IoC. I have the following classes.
// Repository
public class EFProductRepository : IProductRepository, IUnitOfWorkRepository
{
private IUnitOfWork unitOfWork;
private EFDbContext efDbContext;
public EFProductRepository(IUnitOfWork uow)
{
unitOfWork = uow;
efDbContext = new EFDbContext();
}
//
}
// Controller
public class ProductController : Controller
{
private IUnitOfWork unitOfWork;
private IProductRepository productRepository;
public ProductController(IUnitOfWork uow, IProductRepository repo)
{
unitOfWork = uow;
productRepository = repo;
}
}
Currently my ninject bindings are as follow which assign new instance of the concrete class for the interface.
ninjectKernel.Bind<IUnitOfWork>().To<UnitOfWork>();
ninjectKernel.Bind<IProductRepository>().To<EFProductRepository>();
using my ninject controller factory, I need to inject same instance of the IUnitOfWork class to the ProductController and EFProductRepository. Please guide me.

Categories