.NET Core DI without constructor arguments - c#

Until now, I have used the Unity IOC container to resolve dependencies, which works just fine. With the Unity DI, I normally resolve instances in the following way:
Public class TestClass {
public TestClass()
{
var instance = IOC.resolve<InterfaceClassToResolve>();
}
}
This works great, but seeing that .net core now provides me with an out of the box DI container, I would much rather like to use that - There is just one problem compared to the Unity IOC, namely that it is injected as a constructor argument, and not resolved like the example above.
In most cases, I figured that it forces me to chain my dependencies throughout multiple classes, instead of just resolving my dependency in the classes that actually needs them.
I have been looking at ways to solve this, and as far as I can see, the only option is to do something like this:
Public class TestClass {
public TestClass(IServiceProvider serviceProvider)
{
var instance = serviceProvider.GetService<InterfaceClassToResolve>();
}
}
And then we are back to square one again...
Therefore, am I missing some of the functionality behind the .net core IOC, or is there some secret sauce to why most examples wants me use the .net core IOC via constructor arguments?

You can use DI without constructors like:
On the ConfigureServices
services.AddSingleton<YourClass>()
Then inject it like this:
private YourClass YourClass
{
get
{
return this.serviceProvider.GetRequiredService<YourClass>();
}
}

As already commented, Service Locator pattern is not the best method and considered an anti-pattern.
I understand the necessity, though, of finding a way to easily convert existing code to the out-of-the-box DI system without going mad.
I therefore suggest you to do something like this:
1) Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DatabaseContext>(
options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
// other services configuration here
// IMPORTANT: This should be the last line of ConfigureServices!
IOC.CurrentProvider = services.BuildServiceProvider();
}
...
2) IOC.cs
public class IOC
{
public static IServiceProvider CurrentProvider { get; internal set; }
public static T resolve<T>()
{
return CurrentProvider.GetService<T>();
}
}
This should allow you to use dotnet core DI with existing service locator code based on Unity, with minimal fixes (basically just some using declarations to be fixed), as long as you solemnly promise to refactor your code as soon as possible to get rid of all that Service Locator code :D

Related

How is Pure DI implemented with Razor Pages

This question is similar to my previous question about Razor Components, but instead, this question is about Razor Pages, which requires a different interception point.
I am making an ASP.NET Core application using the Pure DI approach explained in the book Dependency Injection Principles, Practices, and Patterns (DIPP&P). Part of my application has a web API controller. To implement Pure DI with my controller, I was easily able to follow section 7.3.1 "Creating a custom controller activator" from DIPP&P to create a controller activator class, similar to the example found in DIPP&P. This was done by implementing IControllerActivator and composing my composition root within the create method.
My application will also feature Razor Pages. I would like to continue using the Pure DI approach but I cannot find any examples on how to do this. My assumption is I need to create a RazorPageActivator class, which implements IRazorPageActivator and add my composition root to the Activate method. However, after reviewing the RazorPageActivator class found in the ASP.NET Core GitHub, it looks very complex and I fear if I intercept it (or override it?) by making my own class that implements IRazorPageActivator things will break and I'll be in a mess.
My question is how does one go about implementing Pure DI with Razor Pages, if possible?
With Razor Pages, the IPageModelActivatorProvider functions as your Composition Root's Composer. Here's an example based on the default Visual Studio (2019) Razor Pages project template.
Let's start with the custom IPageModelActivatorProvider, which acts as your Composer, which is part of your Composition Root:
public class CommercePageModelActivatorProvider
: IPageModelActivatorProvider, IDisposable
{
// Singletons
private readonly ILoggerFactory loggerFactory;
public CommercePageModelActivatorProvider(ILoggerFactory loggerFactory) =>
this.loggerFactory = loggerFactory;
public Func<PageContext, object> CreateActivator(
CompiledPageActionDescriptor desc) =>
c => this.CreatePageModelType(c, desc.ModelTypeInfo.AsType());
public Action<PageContext, object> CreateReleaser(
CompiledPageActionDescriptor desc) =>
(c, pm) => (pm as IDisposable)?.Dispose();
private object CreatePageModelType(PageContext c, Type pageModelType)
{
// Create Scoped components
var context = new CommerceContext().TrackDisposable(c);
// Create Transient components
switch (pageModelType.Name)
{
case nameof(IndexModel):
return new IndexModel(this.Logger<IndexModel>(), context);
case nameof(PrivacyModel):
return new PrivacyModel(this.Logger<PrivacyModel>());
default: throw new NotImplementedException(pageModelType.FullName);
}
}
public void Dispose() { /* Release Singletons here, if needed */ }
private ILogger<T> Logger<T>() => this.loggerFactory.CreateLogger<T>();
}
Notice a few things with this implementation:
The structure of this class is very similar to the one's given in the book's code samples.
It implements IDisposable to allow disposing of its own created singletons. In this case, no singletons are created in its constructor, so nothing needs to be disposed. The ILoggerFactory is "externally owned"; it is created by the framework, and will be disposed (if needed) by the framework.
The class uses a custom TrackDisposable extension method (shown later on) that allows tracking scoped and transient dependencies. The TrackDisposable method will add those instances to the request and allows the framework to dispose them when the request ends.
This is why the CreateReleaser method only disposes the Page itself. The disposing of all other created components is done by the framework when you track them for disposal. You can also choose to track the Page itself; in that case you can leave the CreateReleaser delegate empty.
There is a handy Logger<T>() method that simplifies the creation of ILogger<T> implementations. Those come from the framework and are created by the ILoggerFactory.
Here's the TrackDisposable extension method:
public static class DisposableExtensions
{
public static T TrackDisposable<T>(this T instance, PageContext c)
where T : IDisposable
{
c.HttpContext.Response.RegisterForDispose(instance);
return instance;
}
}
The last missing piece of infrastructure required is the registration of your CommercePageModelActivatorProvider into the framework's DI Container. This is done inside the Startup class:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
// Register your custom component activator here
services.AddSingleton<
IPageModelActivatorProvider, CommercePageModelActivatorProvider>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
}
}

Is there any way to validate the lifetime in DI?

I'm looking for some way to enforce the checking (runtime, of course) of the proper lifetime registration of dependency-injection services, in .Net Core or higher.
Let's say I have a stateful service like this one:
public class MyStatefulService
{
private object _state;
}
However, by mistake, I could register it with the wrong lifetime:
services.AddTransient<MyStatefulService>();
So, I won't be alerted, but the actual behavior is not what I'd expect: the service is created at every request, and the state won't be preserved.
I wonder if there is a way to reinforce this pattern. For instance, it would be nice if I could decorate the class with an attribute like this:
[Singleton]
public class MyStatefulService
{
private object _state;
}
at this point, possibily at startup or at the very first request, the framework should throw if the registration is different than AddSingleton (along its overloads).
Similarly, the subject could apply for transient-only services, which shouldn't registered as singletons.
The only solution came in my mind is rather naive, and I don't like so much:
//line of principle code
public static class MySingletonChecker
{
private static HashSet<Type> _set = new HashSet<Type>();
public static void Validate(Type type)
{
if (_set.Contains(type))
{
throw new Exception();
}
else
{
_set.Add(type);
}
}
}
public class MyStatefulService
{
public MyStatefulService()
{
MySingletonChecker.Validate(this.GetType());
}
private object _state;
}
Is there any better solution, hack or anything that helps to prevent errors?
If you want to idiot-proof your code, you can provide an extension method to IServiceCollection that registers your service exactly the way it should be.
public static void AddMyStatefulService(this IServiceCollection services)
{
services.AddSingleton<MyStatefulService>();
}
Then in your services configuration section, the developer would type:
services.AddMyStatefulService();
Here's a way like I was pointing out in the comments
Let's have some empty types:
public class ScopedService {}
public class TransientService {}
Let's have a real service that derives from one of the empty types:
public class RealService: ScopedService, IRealService {
//impl
}
And a generic registration method helper:
static void MyAddScoped<TService, TImplementation>(IServiceCollection services)
where TService : class
where TImplementation : ScopedService, TService
{
services.AddScoped<TService, TImplementation>();
}
Let's register our realservice using the helper:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
MyAddScoped<IRealService, RealService>(services);
}
RealService is a ScopedService - think of this as "how you decorate a service to insist it be added as scoped"
Suppose the developer changes the service to be a transient:
class RealService: TransientService, IRealService {
Now you get a compiler error from the helper method:
The type 'YourApplication.RealService' cannot be used as type parameter 'TImplementation' in the generic type or method 'Startup.MyAddScoped<TService, TImplementation>(IServiceCollection)'. There is no implicit reference conversion from 'WebApplication1.RealService' to 'WebApplication1.ScopedService'.
Your "one person who looks after registration" can know that the developer is indicating the service is no longer registerable as Scoped and can change it (and the build will be broken until it is changed, which is a good way of preventing accidental release of incorrect code)
Another way to validate lifetimes, is by inspecting the entire DI container in the ConfigureServices clause.
Each member of a IServiceCollection has a LifeTime property which gives you the information you're looking for: https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.servicedescriptor.lifetime?view=dotnet-plat-ext-5.0#Microsoft_Extensions_DependencyInjection_ServiceDescriptor_Lifetime
To move DI composition to the declaration of a class you could work with some self-made marker interfaces like IRegisterTransientServiceAs<T>and add it to your class like this:
public class MyStatefulService : IMyStatefulService, IRegisterSingletonServiceAs<IMyStatefulService>
Within your composition you have your own extension method that iterates through all loaded types within the application domain, searches for the given generic interface and register them with the declarated lifetime from the given interface.
Maybe this is not real DI, but as you already mentioned, mostly the lifetime of a service is baked into the code of the service itself and it happens very rarely that a specific service will be used in different project with different lifetimes. So IMHO it is okay to bake the desired lifetime into the class itself, instead of making the decision outside.

C# .NET Core Configuration - alternative approaches?

I am looking for simple approaches to the use of the Options pattern for mixes of environment-agnostic, environment-specific and secret configuration in .NET Core. I have seen unnecessarily complex approaches to this, and developed one approach which feels much simpler than what I have seen, but still begs to be simplified further. I will provide that in the first answer to this question.
So, put as a clear question:
What is the simplest approach to Binding Options objects to Configuration sections in .NET Core that is a consistent approach across all types of .NET Core projects, e.g. Function apps, Worker services, ASP.NET Core, etc?
Bonus questions:
How can this approach be used without requiring the use of a Dependency Injection container?
creating an instance of IConfiguration with a Dependency Injection container feels very messy to me in that IConfiguration then needs to be a parameter of every constructor within a chain of dependencies, or it requires that all class/interface implementations need to be registered within the DI container.
How can this approach be used with a Dependency Injection container?
most people I've met do use DI containers (either Autofac or the .NET Core DI container) so it's definitely worth discussing how the approach might also be useful in a DI container scenario.
===========
It's worth noting that I completely adhere to the Dependency Inversion principle via Dependency Injection, but do so via chained constructors (typically two) and only minimally use DI containers in .NET Core - almost always for logging only. There are a number of reasons for this which are probably best stated by Ygor Bugayenko in Elegant Objects and not the topic of this post.
===========
One more thing:
I am not going to accept my own answer that I'm providing below. In fact, I'm not going to accept an answer for awhile so that there is plenty of time for alternate approaches to be provided in the answers.
Looking forward to your ideas! Cheers
One approach to this is to create Options objects that lazy-initialize, and use an implementation of IConfiguration that has been stored in a singleton at startup that is available to the entire application in order to eliminate the need for DI container gymnastics. I believe that the following approach does not diverge from Microsoft's intent regarding the use of the Options pattern, but is a different and IMO simpler approach to doing so.
In this example implementation I'm going to use naive Singleton patterns for simplicity - if you're concerned at all with multiple threads creating multiple instances you might go with the use of the Lazy class or a traditional double-locking singleton pattern.
I'll use a RemoteCache configuration object as an example of an Options compliant model:
public class RemoteCache
{
private const string SectionName = "Redis";
private static RemoteCache _instance;
private static readonly Redis RedisConfig = new();
public static RemoteCache Instance()
{
if (_instance is not null) return _instance;
_instance = new RemoteCache();
return _instance;
}
private RemoteCache() { }
public string CacheConnection => RedisConfigInstance.CacheConnection;
public string CacheKey => RedisConfigInstance.CacheKey;
private Redis RedisConfigInstance
{
get
{
if (string.IsNullOrWhiteSpace(RedisConfig.CacheConnection) is false) return RedisConfig;
AppConfiguration.Instance.GetSection(SectionName).Bind(RedisConfig);
return RedisConfig;
}
}
private class Redis
{
public string CacheConnection { get; set; } = string.Empty;
public string CacheKey { get; set; } = string.Empty;
}
}
Q. What is AppConfiguration and where does this get initialized?
A. A static class that gets initialized in your Startup class.
My Startup class for a function app typically looks like this. You might notice that I am using "appsettings.json" which is typically not done in function apps, but I wanted the environment-agnostic portion of my configuration to follow the same pattern used in non-function-apps, rather than shoving dang-near everything into Environment Variables which seems pretty typical of function apps and leads to a glut of environment variables being pushed in during the deployment process. I do use environment variables for secrets in non-local deployments, and use KeyVault references to acquire those secrets at runtime. When running locally, secrets are acquired using the UserSecrets.
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
ExecutionContextOptions executionContextOptions = builder.Services.BuildServiceProvider().GetService<IOptions<ExecutionContextOptions>>().Value;
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
.SetBasePath(executionContextOptions.AppDirectory)
.AddEnvironmentVariables()
.AddJsonFile("appsettings.json", false)
.AddJsonFile("local.settings.json", true)
.AddUserSecrets(Assembly.GetExecutingAssembly(), true);
AppConfiguration.Instance = configurationBuilder.Build();
builder.Services.AddLogging(logging =>
{
logging.AddApplicationInsights(new ApplicationInsightsConfiguration().AppInsightsInstrumentationKey());
}
}
}
This is all the AppConfiguration class is:
public static class AppConfiguration
{
public static IConfiguration Instance;
}
So, once you have your startup code and AppConfiguration class in place you can happily create Options model objects that map to your configuration sections to your heart's content. These models are implemented as singletons so you can then access them from whatever code needs configuration no matter how deeply nested in your application.
Usage example:
(I prefer accessing configuration models through an interface, which allows my code to be TDD with true unit tests that use fakes of config implementations [of course, use mocks if you prefer])
public interface IRemoteCacheConfiguration
{
string CacheConnection();
string RedisCacheKey();
}
public class RemoteCacheConfiguration : IRemoteCacheConfiguration
{
public string CacheConnection() => RemoteCache.Instance().CacheConnection;
public string RedisCacheKey() => RemoteCache.Instance().CacheKey;
}
public class MyThingThatAccessesTheCache
{
private readonly IRemoteCacheConfiguration _remoteCacheConfiguration;
public MyThingThatAccessesTheCache() : this(new RemoteCacheConfiguration()) { }
public MyThingThatAccessesTheCache(IRemoteCacheConfiguration remoteCacheConfiguration) => _remoteCacheConfiguration = remoteCacheConfiguration;
public void DoStuff()
{
string cacheConnection = _remoteCacheConfiguration.CacheConnection();
}
}

Structuremap IContainer Implementation

I am currently trying to get my head around structuremap now that the ObjectFactory static function has been marked as obsolete.
In the long run I have to use this in a MVC and WebApi application. When previously used, a line to a static method was placed in the the global.asax to initialise everything using the ObjectFactory.
ObjectFactory.Initialize{
container.For .....
}
Trying to convert this to the new IContainer approach I have come up with the following however am wondering if I have actually inadvertently implemented this often mentioned Anti-Pattern in my approach.
Static method to return container:
public class StructureMapConfig
{
public static IContainer GetContainer()
{
return new Container(container =>
{
container.For<IUserService>().Use<UserService>();
container.For<IStringService>().Use<StringService>();
container.For<IUserRepository>().Use<UserRepository>();
});
}
}
Userservice's contstructor looks like this:
public class UserService : IUserService
{
private readonly IUserRepository _userRepository;
private readonly IStringService _stringService;
public UserService(IUserRepository userRepository, IStringService stringService)
{
_userRepository = userRepository;
_stringService = stringService;
}
Finally the initialise (this instance in a console app) looks somthing like this:
private static IUserService _userService;
private static IContainer _container;
static void Main(string[] args)
{
_container = StructureMapConfig.GetContainer();
_userService = _container.GetInstance<IUserService>();
}
So to my questions.
Am I doing anything seriously wrong here
In the UserService, should I be passing the IContainer in and using the object factory to get the instance or should I leave as is.
Is returning the IContainer from the static method the best approach
If this was a MVC app, is it best practice to build this once in the Global.asax or should the controller constructor call the static method every time.
Thanks for any advice.
To go through your questions in order:
Am I doing anything seriously wrong here
No, I don't see anything seriously wrong here. There are a few improvements you could make that I'll talk about shortly.
In the UserService, should I be passing the IContainer in and using
the object factory to get the instance or should I leave as is.
You're correct in injecting UserService over an instance of IContainer. If your controller only requires the UserService then why inject the entire container. Really you only want to inject the bare minimum of what you need to reduce unnecessary coupling and dependencies.
Is returning the IContainer from the static method the best approach
Within the removal of the ObjectFactory then yes, returning an instance of the container via a static method is a common approach for those classes whose creation is not managed via MVC's Dependency Resolution.
If this was a MVC app, is it best practice to build this once in the
Global.asax or should the controller constructor call the static
method every time.
Creating the container in Global.asax.cs is your best approach as it's done once on Application_Start, however see below for my recommendation of using a nested container per http request.
Improvements:-
Take advantage of StructureMap's registries:
Instead of referencing the dependencies directly like this:
public static IContainer GetContainer()
{
return new Container(container =>
{
container.For<IUserService>().Use<UserService>();
container.For<IStringService>().Use<StringService>();
container.For<IUserRepository>().Use<UserRepository>();
});
}
Opt to use StructureMap's registries instead. This way you can group your dependencies (such as MVC specific dependencies or WebAPI specific dependencies, like so:
public class WebsiteRegistry : Registry
{
public WebsiteRegistry()
{
this.For<IUserService>().Use<UserService>();
this.For<IStringService>().Use<StringService>();
this.For<IUserRepository>().Use<UserRepository>();
}
}
Then load your registries like this:
container.Configure(c => {
c.IncludeRegistry<WebsiteRegistry>();
c.IncludeRegistry<TaskRegistry>();
});
HTTP Context bound containers:
Another recommended pattern when using StructureMap with ASP.NET MVC or WebApi (or any HTTP based application) is to use nested containers that are bound to each HTTP request. This basically involves creating a new nested container on each HTTP request and then disposing it at the end of the request. This ensures that dependencies such as session objects, database connections, or UoW contexts are disposed of as soon as the HTTP request is over.
I would recommend taking a look over this article which goes into more detail on the matter and talks about how this can be set up.
This is exactly the same technique that's used in the StructureMap.MVC5 package that's often recommended by StructureMap's creator, Jeremy Miller.
Auto registering dependencies
Instead of registering every dependency with StructureMap manually you can take advantage of StructureMap's auto-registration. You can also specify your own scanning conventions.

Achieving DI without 3rd party framework

I am writing a plugin as part of a plugin architecture. The way plugins are created is via reflection and CreateInstance. Therefore the default constructor is called. This code I cannot touch and I am trying to find a sensible way to use DI without the ability to use a framework.
I believe I have 3 options:
i) Poor Man's DI (PMDI)
ii) Factory Pattern
iii) TinyIOC or similar (one cs file that handles DI)
I started looking at PMDI but then a dependency needed another dependency so I ended up with something similar to this which is ugly and could get worse:
public MyMainPluginClass() : this(new Repo(new Logger()))
{
}
public MyMainPluginClass(IRepo repo)
{
}
I then moved onto the idea of a Factory Pattern but could not find any decent demo code. I assume I would have something like this:
public static FactoryUtility
{
public static IRepo GetRepo()
{
return new Repo(GetLogger());
}
public static ILogger GetLogger()
{
return new Logger();
}
}
public MyMainPluginClass() : this(FactoryUtility.GetRepo())
{
}
public MyMainPluginClass(IRepo repo)
{
}
Is that how it would look?
I then came across TinyIOC which is one class that does all the dependency registering but I believe it requires to be setup in a Program.cs which I don't have in a class library. If someone has any experience using this could it be used like so:
public MyMainPluginClass()
{
var container = TinyIoCContainer.Current;
container.AutoRegister();
var implementation = container.Resolve<IRepo>();
MyMainPluginClass(implementation);
}
public MyMainPluginClass(IRepo repo)
{
}
Are there any alternative approaches to achieve DI without using a 3rd party library and if not which approach would choose from above?
NOTE: The code above has not been compiled and is just an idea of what I think would work. Please post corrections if they are valid approaches.
Since you're using .NET 4, you might want to consider using MEF, as it's built into the framework itself. This looks like fairly straightforward DI, which MEF handles well, as it's intended mainly for extensibility.
For details, see the Learn More page on the MEF CodePlex site.
I went with TinyIOC in the end. Unfortunately the plugin's constructor gets called several times before its actually up and running. I simply set a boolean to prevent registration being called several times and therefore it allows me to simply auto-register dependencies and off we go.
public MyMainPluginClass() : this(FactoryUtility.SetupIOC())
{
}
public MyMainPluginClass(IRepo repo)
{
}
public static class FactoryUtility
{
private static bool Initialized = false;
public static IRepo SetupIOC()
{
var container = TinyIoCContainer.Current;
if (!Initialized)
{
container.AutoRegister(new[] { Assembly.GetExecutingAssembly() });
Initialized = true;
}
var result = container.Resolve<IRepo>();
return result;
}
}
If I absolutely don't want to add a dependency to a DI container, I like to use my own TinyIOC (sorry about the name, didn't know it was taken), which for small projects gives me the same semantics as using a container, but clocks in at below 200 LOC.
If you are interested, here is the code: https://gist.github.com/ad7608e2ae10b0f04229

Categories

Resources