Multiple Dependency Injection in Automapper class - dependency-injection

I'm working on an WebApi project, where I'm using Automapper to map certain Dto's to Entities. So far i needed only one dependency injected for manually mapping a certain property. Now I want to inhject another dependency. My constructor in the AutoMapper class looks like this:
public MapperConfig(
IRoleRepository roleRepository, IActivityRepository activityRepository)
However, I have trouble instatiating the MapperConfig class in the Startup.cs :
services.AddSingleton<IMapper>(provider => new MapperConfiguration(cfg =>
{
cfg.AddProfile(new MapperConfig(
services
.BuildServiceProvider()
.GetService<IRoleRepository, IActivityRepository>()));
}).CreateMapper());
So far I had no problems using the GetService method, because I was passing only one dependency. But if the constructor of the automapper takes multiple parameters, I don't know how to invoke it properly. Any help will be appreciated. Thank you for your time.

Related

Asp.net core 2.0 AutoMapper IValueResolver dependency injection

I have tried most of the examples in the Google Results, Stackoverflow and in AutoMapper. But was not able to get the IValueResolverdependancy injection to work.
I have below service
public class StorageService : IStorageService
{
private readonly BlobServiceSettings _blobServiceSettings;
public StorageService(IOptions<BlobServiceSettings> blobServiceSettings)
{
_blobServiceSettings = blobServiceSettings.Value;
}
// some methods I need
}
This is my profile
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Building, BuildingEnvelope>(MemberList.None)
.ForMember(dest => dest.ImageUrl, opt => opt.ResolveUsing<BuildingImageUrlResolver>());
}
}
this is my IValueResolver
public class BuildingImageUrlResolver : IValueResolver<Building, BuildingEnvelope, string>
{
private readonly IStorageService _storageService;
public BuildingImageUrlResolver(IStorageService storageService)
{
_storageService = storageService;
}
public string Resolve(Building entity, BuildingEnvelope envelope, string member, ResolutionContext context)
{
return _storageService.MyMethod(entity.ImageFileName);
}
}
I get the below error in my inner exception
No parameterless constructor defined for this object.
Not sure what I am doing wrong.
Thanks in advance
Neo
Lucian's suggestion is correct -- the AutoMapper.Extensions.Microsoft.DependencyInjection package is the way to go. Even if you don't want to use it, you'll have to do something similar.
I've had this very same problem and by using the extensions, you just modify the entrypoint from which you register AutoMapper and its configuration.
What the extensions do (source) is:
Initializes Automapper with the configuration provided
It scans for all classes you have that you could be implementing with dependency injection and registers them as transient, looking for implementations of the following:
IValueResolver
IMemberValueResolver
ITypeConverter
IMappingAction
The assemblies that it will scan actually depend on the parameters that you provide on the call.
If any of these can be actually instantiated, then they will be registered as transient implementation.
And just like that, AutoMapper will request instances of these to the service provider, which will resolve them, and to do that, it will also resolve any pending dependencies.
Note that this is actually very simple -- the most difficult part is scanning the right assemblies and registering the right classes. You can do it manually too, but these extensions already take care of it for you.
Mind you, even when reflection has been improved a lot, this process is relatively slow, so try not to abuse it too much (for instance, in tests).
Finally, if none of that works for you, remember that you need to setup AutoMapper to use the dependency injection resolver too:
automapperConfiguration.ConstructServicesUsing(serviceProvider.GetService);

How to share a DbCOntext in n-tier repository pattern. Asp .net mvc

Firstly i must say, i know their is a very close question i found on stackoverflow, but my question is a little different.
I have n-tier application in asp .net mvc, in which I have: A BOL project(which has EF classes and db object etc), BLL project(which has buiseness logic), than we have DAL project(which has db interaction logic, and it uses EF dbcontext from BOL). And a main mvc project which ahs controllers and views etc.
Now, we are using repository pattern, we have many Repositories in BLL with their interfaces. And also we have many repositories in DAL which are without interfaces though. But all of those DAL repositories have one DbContext member in them, which is being created in their constructors, so each DAL repository is interacting with separate instance of DbContext which it has created.
And in our main mvc project, we have used ninject to inject BLL repositories in controllers constructors (in request scope). Now, the issue we are facing is, that each BLL repository has references to one or more DAL repositories, and each of those DAL repositories are using their own seperate DbCOntext. Which is wrong and bad, thats why i am looking for the way to share one DbCOntext in all DAL repositories, per request(No matter how many BLL repositories ninject injects in my controller, just make sure only one DbContext instance is being created and used per request). And dispose that context after each request.
One way i thought was to not create DBcontext in constructor of DAL repositories. But have some method call(say initiateDbContext) for that, than also add this method in BLL repositories, which do nothing but to call the smae method of their member DAL repositories. Call that method for one BLL repository in controller constructor, and than have a method to get and set db contexts in all other repositories from the first repository. But i know this is bad approach, firstly we are creating DbContext in controller, which should be in DAL only, secondly i am adding create, get and set DbCOntext methods in DAL as well as in BLL repositories, because i need to pass DbCOntext to BLL which will pass that to the DAL repositories it communicates with internally. And that's very bad.
That's why i am asking here for any good pattern to achieve "ONE DBCONTEXT PER REQUEST IN N-TIER WITH REPOSITORY PATTERN."
If you are using dependency injection, you should use it all the way, not only in the controllers.
That means, the DBContext should be injected into the Repositories, and Ninject should be configured to resolve your DBContext with per request lifetime.
Based on the answer from #atika i searched further and implemented what he suggested(using ninject/DI in whole application rather than just in one main project of mvc) and it solved the issue, i am posting this answer to add more details and some extra issues i faced and i got to spend time googling about further, so others might save some time.
Idea is to use dependency injection throughout the solution, no matter how many projects/tiers you have in it and no matter how many repositories you have got.
So, the issue comes to the point, that if we want to use ninject or any other DI for binding all dependencies from all tiers/projects, we should have reference to all of those tiers/projects in our main mvc project, so that we can bind the dependencies in NinjectWebCommons, but this will kill the whole purpose of n-tier architecture. We don't want to do that, we want our hierarchy to sustain, like in my case
MainMVCProject->BLL->DLL->DB
So, for this, i found a very helpful article Ninject with N-Tier MVC Application - Inject Object in Business Layer.(Their are also some other approaches, one is to make a project just for bindings and add use that project to bind all dependencies, but that sounds like over engineering and overkill)
Based on which i added the following class in my BLL tier/project(after installing ninject in this project and DAL project too), which has bindings for DLL classes.
using BLL.Repositories;
using BLL.RepositoryInterfaces;
using Ninject.Modules;
using Ninject.Web.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DAL;
using BOL;
namespace BLL
{
public class LayerBindings : NinjectModule
{
public override void Load()
{//add all references here like these
Bind<AdDb>().ToSelf().InRequestScope();
Bind<db_Entities>().ToSelf().InRequestScope().WithConstructorArgument("ConnectionString", BOL.CommonFunctionsBOL.ConnectionString);
}
}
}
Getting some help from howto-ninject-part-1-basics article, i managed to do many things with ninject, and used many of its features.
Now, you can see i added the bindings of DLL project in this class, which were not accessible in main mvc project. Now, i just need to load these bindings in main ninject.
Now, in NinjectWebCommons.cs file, i added following lines:
//old bindings of BLL and local project.
kernel.Bind<IUserRepository>().To<UserRepository>().InRequestScope();
//now here we bind other dependencies of DAL etc using class we added in BLL
var modules = new List<INinjectModule>
{
new BLL.LayerBindings()
};
kernel.Load(modules);
(In RegisterServices method, after local bindings and BLL objects bindings.)
After doing just this, ninject started working in all the projects and i just used constructor injection or on some places, property injections and all worked fine.
PS1: I also used property injection*(i read that this is not recommended to use property injections, use them only where you cant use constructor injections.)* for private properties and they had to be enabled with kernel.Settings.InjectNonPublic = true; line in "CreateKernel" method before returning the kernal.
Now my property injection is working for private properties too, like this:
[Ninject.Inject]
private SomeDALObject db { get; set; }
PS2: I also installed ninject.web.webapi nuget package for ninject to work with webapis, and also found this line to get an object anywhere from ninject.(I don't know if this is a good way or not, but it does return a fully constructed object which i used than. If any one can clarify or correct me if using this is right or not, that will be great.)
((TypeOfObjectYouWant)System.Web.Mvc.DependencyResolver.Current.GetService(typeof(TypeOfObjectYouWant))).DoSomething();
I hope this might help some people like me looking for proper guide on this issue.
You can write one BaseRepository and implement BaseRepository in all repository classes.
public class BaseRepository
{
public StudentEntities dbStudentEntity;
public BaseRepository()
{
dbStudentEntity = new StudentEntities();
}
}
DataRepository :
public class CurrencyData : BaseRepository,ICurrencyData
{
public List<Models.Currency> GetCurrencyList()
{
var objCurrencies = dbStudentEntity.Currencies.ToList();
List<Models.Currency> currencyList = new List<Models.Currency>();
foreach (var item in objCurrencies)
{
var model = new Models.Currency { CurrencyId = item.CurrencyId, Currency1 = item.Currency1,Code = item.Code,Symbol = item.Symbol,Country = item.Country };
currencyList.Add(model);
}
return currencyList;
}
}

Accessing IAuthSession in non-controller classes in ServiceStack/MVC4

I am new to ServiceStack, so this is probably a noob question:
I am working on an ASP.NET MVC4 application that uses ServiceStack and am trying to figure out how I could get a hold of the current IAuthSession from within a class (either a EF context or a PetaPoco Database) used by my MVC4 controllers derived from ServiceStackController.
The class in question is registered with Funq with the ReuseScope.Request scope (i.e. on the per-HTTP request basis), and ideally I'd like every instance of it to be autowired with the current IAuthSession using either a constructor parameter or a public property.
How do I do that?
UPDATE
After some digging I came up with what I think might work.
In my AppHost.Configure I register a lambda that returns a session from the current request:
container.Register<IAuthSession>(c =>
HttpContext.Current.Request.ToRequest().GetSession());
Also:
container.RegisterAutoWired<EFCatalogDb>();
where EFCatalogDb is my EF context that takes IAuthSession as a constructor argument:
public class EFCatalogDb : DbContext
{
public EFCatalogDb(IAuthSession session) : base()
{ }
// ...etc....
}
Unfortunately I am not at the point in my development when I can test this workaround, so have to ask others if it makes sense at all.
My first suggestion would be to try to keep IAuthSession out of your database classes since that creates a dependency on ServiceStack that seems unnecessary.
That being said, I think you could go the route of registering IAuthSession and having the container automatically inject IAuthSession. A better way might be creating your own 'wrapper class' around IAuthSession and injecting that into your database classes. That would then break the dependency on ServiceStack.
If you have no issue keeping a dependency on ServiceStack another possibility would be using the SessionFeature class and doing something like
var key = SessionFeature.GetSessionKey();
authSession = AppHost.Resolve<ICacheClient>().Get<IAuthSession>(key);

Dependancy issue with static utility classes with repository (.NET MVC project)

I have an MVC project with the standard IoC setup that uses StructureMap to inject repositories into controller constructors.
I also decided I wanted to have a static "utilities" class where I could have common methods that can be called by different controllers. So for example, I have:
public static IEnumerable<CountryCode> GetCountryList()
{
ICountryCodeRepository repo = ObjectFactory.GetInstance<ICountryCodeRepository>();
IEnumerable<CountryCode> countries = repo.GetAll();
return countries;
}
As you can see, that directly creates a repo object from the ObjectFactory. The problem, now, is that when I want to unit-test my controllers, I can mock the repos for the controllers, but not the repos in the utilities class (which the controller eventually calls) I'm sure there are other reasons why my utilities class is wrong, but this is what I see so far. I've also read some stuff saying what I have is bad design, I just don't know how to fix it.
I was thinking about having the GetCountryList() function to accept a repo object
GetCountryList(ICountryCodeRepository _repo)
and the calling controller would pass it in, but isn't that just creating another dependency concern because all controllers will have to know what the utility functions need?
Or is it possible to use StructureMap somehow to inject these utility methods?
It's at least OK that you know that what you are doing is bad design. That's fine and people reading this post will know it as well and avoid doing the same mistake as you.
But now to the point, you could use a provider in your static class:
public static class Foo
{
public static Func<ICountryCodeRepository> CountryRepoProvider =
() => ObjectFactory.GetInstance<ICountryCodeRepository>();
public static IEnumerable<CountryCode> GetCountryList()
{
return CountryRepoProvider().GetAll();
}
}
and now in your unit test you could mock it:
Foo.CountryRepoProvider = () => mocha;
or if you are using ASP.NET MVC 3 and you DI framework uses a dependency resolver you could improve this code by at least making it DI framework agnostic:
public static IEnumerable<CountryCode> GetCountryList()
{
var repo = DependencyResolver.Current.GetService<ICountryCodeRepository>();
return repo.GetAll();
}
Now in your unit test you could of course write a custom dependency resolver which will spit mocked instances of your services.
And now when you look at this code you might really say to yourself: What am I doing? I am writing a static class with one liner methods delegating to a repository I am fetching from the DI. What's the point when I can benefit from my DI framework to directly inject the instance of this repository wherever I need it and then simply call the method I need on it? What am I unit testing in those one liner static methods? Why am I wasting my time.
And if of course you had more complex logic to handle you would simply write a service layer which will take the necessary repositories as constructor dependencies and perform the complex business operations on them. Then you will simply configure your DI framework to inject those ready to be used instance of the service in your controllers or wherever you need it. See? No need of any static class. Weak coupling and unit testing friendly code.

How do I inject logging into my EF based partial model class?

I'm using the Nuget downloads of Ninject 3.x & NLog 2.x. I've gotten ILogger working via constructor injection on my controller classes, but I don't know how to make it work within my model classes. My model is a partial class tied to a class generated by ADO.NET EntityObject Generator.
I've tried Property Injection with and without the [Inject] attribute, but it always comes back null. I'm not sure what I need to do as the controller constructor injection was all automatic.
Ultimately I think I'd like to move my Models into their own library so they can be reused, but for now I'd be happy with any answer (even specific to asp.net mvc 3 projects) to get this working.
Looks like EF doesn't really allow IoC to be used for creating models, at least without modifying their T4 template. One suggestion I can give is to use ObjectMaterialized event of your ObjectContext like this:
partial void OnContextCreated()
{
ObjectMaterialized += BAEntities_ObjectMaterialized;
}
public void BAEntities_ObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
{
if (e.Entity is MyEntityWithLogging)
{
//apply initialization logic here
((MyEntityWithLogging)e.Entity).Logger = kernel.Get<ILogger>();
}
}
Entities shouldn't have any dependencies. Therefore they should't be created by the IoC container. Rethink your design so that business logic isn't in your entities anymore.

Resources