Dependency injection pattern for polymorphism in ASP.NET - c#

I am reading about DI pattern in ASP.NET. I know it can create a instance inside another class. For example, we have class HomeController need to have service instance like this:
class HomeController{
private IService service;
public HomeController(IService s){
this.service = s;
}
}
IService is implemented by WaterService class.
And we have code to register class which can be created instance, the instance can be type of transient, scope or singleton:
using DependencyInjectionSample.Interfaces;
using DependencyInjectionSample.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IService , WaterService>();
var app = builder.Build();
Then I realize, if IService is implemented by both class WaterService and ElectricService, I have some situation, for example:
Call api to url .../service/waterService: show infomation of waterService.
Call api to url .../service/electricService: show inffomation of electricServic.
how can we register one of these class instance base on situation?

I had some problem but resolved by help of The Answer was given by Shahar Shokrani
Let me know if still facing to implement DI.

Related

How to use NLog in static class where everything else is wired with Autofac

My MVC app is wired with Autofac. I have also configured NLog which works as expected in my controller classes. My nLogger is registered as below:
var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(LoggerService<>))
.As(typeof(ILoggerService<>)).SingleInstance();
var container = builder.Build();
And the constructor of the ILoggerService is:
public LoggerService()
{
SourceClass = typeof (T).FullName;
Logger = LogManager.GetLogger(SourceClass);
}
Now I have also got many static helper classes that I use. For example:
public static class Helper
{
public static string GenerateQrBitmap(string secret, string issuer, string userEmail)
{
...
}
}
But I want to be able to use the logger in these Helper classes as well.
This is one of the reasons why static classes aren't great.
You have two options:
Make them not static (and register them with Autofac) and take
ILoggerService as a constructor parameter.
Change their methods
(e.g. GenerateQrBitmap) to take a ILoggerService as a parameter.
I'd suggest the former.
The alternative is to use the Service Locator pattern - and have Helper resolve directly against the container. I will not show you how to do this, since I don't recommend it. It makes the code harder to unit test, and it hides your dependencies. But if you Google Autofac Service Locator static class c# I'm sure you'll work it out.

How does unity resolve the parameters of a constructor?

I've come across some code that looks like this:
var something = this.container.Resolve<ICatManager>();
which in the web config has a mapping from ICatManager to CatManager.
However, CatManager has a constructor which takes 2 parameters, and no default constructor.
How does unity manage to create an instance of it?
Unity, and almost all other service container / service resolvers / service locators, work by analyzing the constructor(s) available, finding the "best one", then injecting parameters.
So, where does these parameters come from? From the service container itself.
For instance, if you have this service:
interface IService { ... }
class ServiceImplementation : IService
{
public ServiceImplementation(IOtherService os, IThirdService ts) { ... }
}
then when you resolve IService Unity will try to also resolve IOtherService and IThirdService recursively. If the actual classes that implement those services also require other services, it does this resolution recursively until everything is OK.
So basically you could think of the resolution call like this:
var os = container.Resolve<IOtherService>();
var ts = container.Resolve<IThirdService>();
return new ServiceImplementation(os, ts);

MVC Controller initializer is being called many times

The problem:
When I'm loading my application is trying to initialize the main controller many times and I would like to know why... that's making me crazy, If one of us had a similar error and want to give me trips about what I have to check, I'll be agreed!!.
MVC3 C# Using Unity as IoC
Controller:
public ValorationController(IServiceProxy serviceProxy,
IHvmService hvmService,
IFamilyGroupService familyGroupService,
IClientService clientService,
IUserService userService,
IOfficeService delegationService,
ISocietyService societyService,
IFamilyService familyService,
IArticleService articleService,
IArticleFinishedService articleFinishedService,
IOrderService orderService)
: base(serviceProxy)
{
FamilyService = familyService;
ArticleService = articleService;
HvmService = hvmService;
FamilyGroupService = familyGroupService;
ClientService = clientService;
UserService = userService;
DelegationService = delegationService;
SocietyService = societyService;
ArticleFinishedService = articleFinishedService;
OrderService = orderService;
}
Your controller will be initialized on every request that involves it.
This is normal and how IIS works.
Also good to know that every Unity Resolve will create by default a new instance. If you do not want that, you should provide a LifeTimeManager
Read Microsoft's articles about Understanding Lifetime Managers and Using Lifetime Managers.
Maybe you want to use something like this:
// Register a default (un-named) type mapping with a singleton lifetime
myContainer.RegisterType<IMyObject, MySingletonObject>(new ContainerControlledLifetimeManager());
// Following code will return a singleton instance of MySingletonObject// Container will take over lifetime management of the object
myContainer.Resolve<IMyObject>();

How do I inject a repository into a custom MembershipProvider using AutoFac

I created a custom membership provider
public class MyMembership : MembershipProvider
{
private IRepository<User> Repo;
}
I figured out how to inject MyMembership using autofac:
builder.Register(c => Membership.Provider);
However, this doesn't work if I have a constructor that takes an IRepository (it only calls the parameterless constructor.) I tried doing changing from a private field to a public property and calling:
builder.Register(c => Membership.Provider).AutoWireProperties();
The problem is, MembershipProvider doesn't have a Repo property, it's only my class.
For the time being, I've not injected anything, and just created an empty constructor where I simply create a new instance of my Repo. But it makes it harder for testing.
So, is there any way that I can use AutoFac to inject my MyMembership, and have it use the injected Repo?
No. It's not possible.
The DependencyResolver is not used for the providers (roles/membership) etc.
I've made a membership provider which uses DependencyResolver internally. All you need to do is to implement IAccountRepository and register it in your container.
http://blog.gauffin.org/2011/09/a-more-structured-membershipprovider/
It's an old post, so i'll just post here my solution as I struggle with it a bit myself.
public class AutofacBootstrapperImp : AutofacBootstrapper
In your autofac builder setup include register for your interface
builder.RegisterType<YourRepo>().As<IRepository<User>>().SingleInstance();
public class CustomMembershipProvider : MembershipProvider
Overload init method and use autofac scope to resolve your type
private IRepository<User> Repo;
public override void Initialize(string name, NameValueCollection config)
{
// use autoface scope to resole service
using (var scope = AutofacBootstrapper.Container.BeginLifetimeScope())
{
Repo = scope.Resolve<IRepository<User>>();
}
if (config == null)
throw new ArgumentNullException("config");
// Initialize the abstract base class.
base.Initialize(name, config);
}
You should also register the IRepository<User>. But to do that you need to access your custom provider by its concrete type.
So something like this:
builder.Register( c => Membership.Provider );
builder.Register( c => ((MyMembership) Membership.Provider).Repo );
That could be made nicer (avoiding casts by registering your implementation) as follows, but not sure on how it then fits in with ASP.NET and its management of provider lifecycles:
builder.RegisterType<MyMembership>();
builder.Register( c => c.Resolve<MyMembership>() ).As<MembershipProvider>();
builder.Register( c => c.Resolve<MyMembership>().Repo );
EDIT:
but from a design standpoint, it looks like your MyMembership class has a dependency on the IRepository<User>, therefor something like this is probably best:
builder.RegisterType<YourRepositoryImplementation>().As<IRepository<User>>();
builder.RegisterType<MyMembership>();
builder.Register( c => c.Resolve<MyMembership>() ).As<MembershipProvider>();
That way the IRepository will be injected into the MyMembership as needed, but also be available for direct consumption by other components, and they all have the lifetime management handled by Autofac.
This scenario is entirely possible. In my Bootstrapper.cs class, I just inject the properties into the providers as such:
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
var lifetimeScope = DependencyResolver.Current.GetService<ILifetimeScope>();
lifetimeScope.InjectProperties(Membership.Provider);
lifetimeScope.InjectProperties(Roles.Provider);
I also have the following:
builder.Register(context => Membership.Provider).ExternallyOwned();
builder.Register(context => Roles.Provider).ExternallyOwned();
however I'm not entirely sure if it's even necessary. I believe the Registers are there in case you want to inject the provider into a type.

Custom Membership provider with dependency injection - how to test

This is similar to Dependency Injection with Custom Membership Provider, but the responses there don't solve the issue for me.
I have a custom membership provider which has a dependency to a repository class. ASP.NET will always instantiate this using the parameter-less constructor, so to resolve the dependency to the repository I have a kind of service locator method ... my ctor looks like this:
public CustomMembershipProvider()
{
_userRepository = AppStart_NinjectMVC3.Resolve<IUserRepository>();
}
And that Resolve method looks like this..
public static T Resolve<T>() where T : class
{
return _kernel.Get<T>();
}
This works fine when I run the web app, because _kernel is correctly setup. However, I need to test the methods on my membership provider.. So when my test code tries to invoke the methods on membership provider it will instantiate a new membership provider class with the paramter-less ctor, which errors because _kernel is not setup.
What I want to do is somehow inject my FakeUserRepository class instead, but how can I achieve that?
I think I have a work round for this...
I've added a ctor to the membership provider which accepts a repository instance, and then I've manually instantiated my membership provider in my test class like this:
var prov = new CableSenseMembershipProvider(new FakeUserRepository());
var config = new NameValueCollection();
config.Add("applicationName", "ddd");
config.Add("name", "CustomMembershipProvider");
config.Add("requiresQuestionAndAnswer", "false");
config.Add("requiresUniqueEmail", "false");
prov.Initialize(config["name"], config);
Once I've dont this I can then invoke that instance and not worry about the parameter-less ctor being called.
As an aside, you still need to add the membership section to your test project app.config or it wont work - which is somewhat confusing!
Why not extract everything out of your custom membership provider into an implementation class and instantiate that class via the service locator then pass all your calls through to that? The implementation class can then be unit-testable and the ugly Membership stuff can be 'right by inspection'.

Categories

Resources