Good Morning,
I have a legacy full framework(4.7) MVC application. This application uses unity for DI.
We need to make use of the Steeltoe.CloudFoundry.Connector.Redis nuget package. This package however is expecting / used by startup.cs which I don't have.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddRedisConnectionMultiplexer(Configuration);
.PersistKeysToRedis();
services.AddDistributedRedisCache(Configuration);
}
What I am trying to figure out is how to use this with unity so I can have the Steeltoe redis connection object available for DI.
Since the steeltoe projects is OSS I could just grab the source and implement directly but then I have to maintain it.
(Speculation) I could have unity generate specific classes in the nuget package...
using Steeltoe.CloudFoundry.Connector.Redis;
....
container.Resolve(RedisCacheServiceCollectionExtensions)
Any other ideas?
TIA
You could do the initial implementation under Steeltoe, submit a pull request and let the community maintain it from there.
Steeltoe's lack of support for any given DI framework isn't intentional, but rather due to a lack of pre-existing demand. We'd be happy to help you through the process of getting the code included if you're interested.
Related
What is the correct way for a Libary to call an object that was injected through Dependency Inject?
Background: I have multiple .NET Core app that uses dependency injection for all major objects and uses libraries for reusability. It is working great. App1 calls Libary1 and Libary2. App2 calls Libary2 and Libary3 etc.
service.AddTransient<Libary1.ILibary1Dependency, Libary1.Libary1Dependency>();
service.AddTransient<Libary2.ILibary1Dependency, Libary2.Libary1Dependency>();
service.AddTransient<Libary2.ILibary2Dependency, Libary2.Libary2Dependency>();
service.AddTransient<Libary3.ILibary1Dependency, Libary3.Libary1Dependency>();
Now in Libary2.ILibary1Dependency there is a method that needs to call a new Libary2.ILibary2Dependency. What is the best way to do this?
Should I just do a new Libary2.ILibary2Dependency(property1, property2...);?
Is it ok in the main app to actually inject the IServiceCollection object and then in the constructor of the Libary2.ILibary1Dependency get the IServiceCollection?
Is there some nugget package that I don't know about that fixes this perfectly?
Note: Libary2.ILibary2Dependency does get called on its own via dependency injection, if you were wondering
As suggested in the comments, keep the libraries independent of the Service Dependency Injection. And let the Caller make the decision to inject them on need basis and it helps to keep the libraries independent of IOC Framework.
If you need to change the IOC Framework or even upgrade to latest versions, you probably need to spend time to update across the libraries, the more these dependencies you have the more house cleaning needed eventually.
I have seen people creating generic wrappers to avoid having specific dependencies on IOC Frameworks, but its kind of overkill.
If all you have is a 3 or 4 projects, it doesn't matter to refactor them away in both directions.
Recently I started working on a new project using .NET Core 2.1 and I decided to use the SOLID principles and create a nice project structure.
It is a Web API project. Everything is working fine I use a lot dependency injection, most of the stuff is easy to test.
And that's the part where I have to register all my services. I am literally having hundreds of lines looking like this:
services.AddSingleton<...>();
or
services.AddScoped<...>();
I have one line for every service and for a small project it would be fine. However when I have hundreds of these it becomes on BIG mess. Basically the whole project is in a super nice order and there comes the Startup.cs that is full of services.AddX statements.
I was think of creating static classes with methods that register the services but that just doesn't look fine.
I will need to add more services in future and I can't just keep creating static classes or filling the old ones because I will end up with the same mess again and it will be more difficult for me to remember where am I registering a given service.
If you really have hundreds of them, you may want to replace the default container with for example Autofac. These type of frameworks supports modules or kind of "subcontainers".
A module is a small class that can be used to bundle up a set of related components behind a ‘facade’ to simplify configuration and deployment.
Replace DI
Autofac modules
You can have each logical group of services (assemly) export its own RegisterServices method. It is the responsibility of that assembly to select lifetime and scope anyway.
For cosmetics, make it an AddMyStuff() extension method in the Microsoft.Extensions.DependencyInjection namespace.
See AddMvc() for an example. Look it up (F12) and notice the difference between the assembly and the namespace it is in.
I am looking to do the equivalent of this:
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
But in a console application. I also have cases where I need to do this in a worker role. I don't want to have to add a reference to the MVC dll all over the place. I am wondering if there is an equivalent for non-mvc projects? I need to stash the container I create so I can access it throughout my application. I thought of creating a static variable, but I'd rather not do this.
I saw there is a CommonSerivceLocator nuget for Simple Injector but oddly it requires 2.8.1 and the latest non-mvc Simple Injector is 2.8.0.
I don't want to have to add a reference to the MVC dll all over the place.
This indicates that you are not applying dependency injection but are doing Service Location, which is an anti-pattern.
If you apply constructor injection to all your components, you will be able to let Simple Injector build up a complete object graph of dependent components (of many levels deep) without any of your components to know about the existence of an IoC container such as Simple Injector or an IoC abstraction such as the Common Service Locator and MVC's IDependencyResolver. This prevents you from referencing your IoC container or such abstraction "all over the place".
So in a Console Application that means that you typically have one place where you resolve the object graph(s). This is the place in the application that already knows about the existence of the IoC container. This place is typically referred to as the Composition Root.
I saw there is a CommonSerivceLocator nuget for Simple Injector but oddly it requires 2.8.1 and the latest non-mvc Simple Injector is 2.8.0.
I seem to have made an error in the build scripts that create the NuGet packages and although NuGet usually applies checks when a package is uploaded, for some reason it failed to check this. I fixed this and pushed v2.8.2 of the CommonServiceLocator adapter to NuGet. But note that we are dropping support for the CSL adapter in v3 of Simple Injector because it leads to bad practice. Don't use it; you don't need it.
I am working with SQL server 2008, .NET4.5, MVC4, EF6 and Ninject3.2.
I have application that needs to be migrated to use DI with Ninject. DbContext that has to be injected in to Controllers is OnlineLegal.
Currently it is used following in each of Actions.
using (var db = new OnlineLegal())
{
...
}
This makes it clearly visible where OnlineLegal is being used and disposed of.
If I would set up ninject kernel.Bind<OnlineLegal>().ToSelf().InRequestScope(); would this be sufficient to make sure that it is disposed properly on each request in MVC4? If not should I manually register OnePerRequestModule? Or use some other way to do it?
It is sufficient. Provided you have installed the Ninject.MVC4 package ;-).
However, there's recently been quite a few question about InRequestScope not working. I think currently the ninject setup is a bit error prone to mistake and/or issues with package installation/upgrade routines.
As such i would recommend to use .InRequestScope() but also add one (exemplar and automated) integration test which verifies that .InRequestScope() actually properly performs the disposal.
That will show you that you've integrated it correctly and if in future there should be trouble with package upgrade routines you'll find out immediately and can fix it, rather than finding out in production or through some obscure effects.
Documentation link: https://github.com/ninject/Ninject.Web.Common/wiki/InRequestScope
Ninject.MVC4 depends on Ninject.Web.Common.Webhost. Ninject.Web.Common.WebHost adds NinjectWebCommon.cs code to your application's app_start folder.
NinjectWebCommon.cs loads the OnerPerRequestModule. However if you remove that file you will break .InRequestScope(). The bad thing about this is, that it fails without exception. You can still bind .InRequestScope() but it just won't have any effect.
I'm having issues with some vague errors popping out of my fluent configuration. I have read that setting up a logging solution will help me zero in on the issue. I would like to use NLog. I understand that I need to use Common.Logging 2.0 and NHibernate.IInterfaceLogger to get it up and running. I'm just not sure how to put the pieces together. My system is based off of the Onion Architecture. I have my Logging service set up for NLog and I have my interface for it, but I'm just a bit confused on where I should bind all of this together. My Fluent NHibernate configuration exists in my Data project. I'm assuming I would want to bind all of this together there.
Any thoughts on this would be awesome! I'm a little lost!
NHibernate.NLog nuget package does this. I use it in a project now.
For the sake of completeness or if that package ever disappears or the user doesn't use nuget.
You add this to your FluentConfiguration:
.ExposeConfiguration(c =>
{
c.SetProperty(#"nhibernate-logger", #"Microfilm.Core.NLogFactory, Microfilm.Core");
})
Implement ILoggerFactory to return a class that implements IInternalLogger. It's pretty straightforward what to include in the IInternalLogger methods; you're just bridging the calls for the NHibernate logger to NLog calls.