Autofac - Lifetime and modules - oop

Problem (abstract)
Given a module which registers dependency X. The dependency X has a different lifetime in a MVC3 app (lifetime per HttpRequest) then in a console application (dependency per lifetimescope with a name). Where or how to specify the lifetime of dependency X?
Case
I've put all my database related code in a assembly with a module in it which registers all repositories. Now the ISession (Nhibernate) registration is also in the module.
ISession is dependency X (in the given problem case). ISession has different lifetime in a MVC3 app (lifetime per request) then in a console app where I define a named lifetimescope.
Should the registration of ISession be outside the module? Would be strange since it's an implementation detail.
What is the best case to do here? Design flaw or are there smart constructions for this :) ?

Given your use case description, I'd say you have a few of options.
First, you could just have each application register their own set of dependencies including lifetime scope. Having one or two "duplicate" pieces of code in this respect isn't that big of a deal considering the differences between the application and the fact that the registrations appear fairly small.
Second, you could wrap the common part (minus lifetime scope) into a ContainerBuilder extension method that could be used in each application. It would still mean each app has a little "duplicate code" but the common logic would be wrapped in a simple extension.
public static IRegistrationBuilder<TLimit, ScanningActivatorData, DynamicRegistrationStyle>
RegisterConnection<TLimit, ScanningActivatorData, DynamicRegistrationStyle>(this ContainerBuilder builder)
{
// Put the common logic here:
builder.Register(...).AsImplementedInterfaces();
}
Consuming such an extension in each app would look like:
builder.RegisterConnection().InstancePerHttpRequest();
// or
builder.RegisterConnection().InstancePerLifetimeScope();
Finally, if you know it's either web or non-web, you could make a custom module that handles the switch:
public class ConnectionModule : Autofac.Module
{
bool _isWeb;
public ConnectionModule(bool isWeb)
{
this._isWeb = isWeb;
}
protected override void Load(ContainerBuilder builder)
{
var reg = builder.Register(...).AsImplementedInterfaces();
if(this._isWeb)
{
reg.InstancePerHttpRequest();
}
else
{
reg.InstancePerLifetimeScope();
}
}
}
In each application, you could then register the module:
// Web application:
builder.RegisterModule(new ConnectionModule(true));
// Non-web application:
builder.RegisterModule(new ConnectionModule(false));
Alternatively, you mentioned your lifetime scope in your other apps has a name. You could make your module take the name:
public class ConnectionModule : Autofac.Module
{
object _scopeTag;
public ConnectionModule(object scopeTag)
{
this._scopeTag = scopeTag;
}
protected override void Load(ContainerBuilder builder)
{
var reg = builder.Register(...)
.AsImplementedInterfaces()
.InstancePerMatchingLifetimeScope(this._scopeTag);
}
}
Consumption is similar:
// Web application (using the standard tag normally provided):
builder.RegisterModule(new ConnectionModule("httpRequest"));
// Non-web application (using your custom scope name):
builder.RegisterModule(new ConnectionModule("yourOtherScopeName"));
I would recommend against simply using InstancePerLifetimeScope in a web application unless that's actually what you intend. As noted in other answers/comments, InstancePerHttpRequest uses a specific named lifetime scope so that it's safe to create child lifetime scopes; using InstancePerLifetimeScope doesn't have such a restriction so you'll actually get one connection per child scope rather than one connection for the request. I, personally, don't assume that other developers won't make use of child lifetime scopes (which is a recommended practice), so in my applications I'm very specific. If you're in total control of your application and you can assure that you aren't creating additional child scopes or that you actually do want one connection per scope, then maybe InstancePerLifetimeScope will solve your problem.

It's common practice to use a one connection per http request. That being the case, connections would be registered using .InstansePerLifetimeScope(). For example, you might do something like:
builder
.Register(c => {
var conn = new SqlConnection(GetConnectionString());
conn.Open();
return conn;
})
.AsImplementedInterfaces()
.InstancePerLifetimeScope();

Related

Adding DbContext for list of context types at runtime

To implement a plug-in system in a AspNet Core Mvc app, I would like a non-generic method to add a data context from a list of assemblies loaded dynamically at runtime, taking a Type parameter like this:
foreach(Type tp in pluginContexts)
{
services.AddDbContext(tp, options => ...);
}
instead of the usual
services.AddDbContext<PluginDataContext>(options => ...);
That's because for dynamically loaded assemblies, I can not provide the TContext type parameter to the AddDbContextPool method, since that's statically compiled and not available at compile time.
Background
This is for a larger Asp.Net Core MVC app. The plugins must be able to both access the main database of the overall app and a separate database of their own.
Plugin assemblies, containing domain code and their private database context are to be dropped in a specified directory.
The main app loads the plugin assembly dynamically upon startup.
The way I am solving this now is to have each controller get the IConfiguration instance injected, obtain the appropriate connection string from the config, and the database context is instantiated in the controller. Not so nice but does work.
One can easily inject a general class into the Services collection with AddScoped<>, and then use it as a sort of ServiceLocator - however, that is considered an antipattern.
I looked into the source code for AddDbContext but honestly I am lost.
Is there any simple way to achieve this?
Solved it by creating an extensibility point in the plugin assembly.
Define an interface in the main app, which all plugins must implement.
public interface IPluginContextRegistration
{
void RegisterContext(ref IServiceCollection services, Action<DbContextOptionsBuilder> optionsAction);
String GetDatabaseName();
}
Create a class implementing this interface (in the plugin). It has access to the type of its private database context, thus can use the generic AddDbContext method:
public class DatabaseRegistration : IPluginContextRegistration
{
public void RegisterContext(ref IServiceCollection services, Action<DbContextOptionsBuilder> optionsAction)
{
services.AddDbContext<Test1DbContext>(optionsAction);
}
public String GetDatabaseName()
{
return "test-plugin-db";
}
}
Then in the main app ASP.Net Startup.cs file, add following code, which calls the RegisterContext() method for each plugin. For example, if you want to use Sql Server:
void RegisterPluginDbContexts(ref IServiceCollection services, List<Assembly> assemblyList)
{
IEnumerable<IPluginContextRegistration> registrars = new List<IPluginContextRegistration>();
foreach (Assembly assembly in assemblyList)
{
registrars = registrars.Concat(GetClassInstances<IPluginContextRegistration>(assembly));
}
foreach (var reg in registrars)
{
String name = reg.GetDatabaseName();
String connStr = Configuration.GetConnectionString(name);
reg.RegisterContext(ref services, options => options.UseSqlServer(connStr));
}
}
For completeness - the method "GetClassInstances" is just a helper method using Reflection to obtain an instance of classes implementing the specified interface.
So it's simple after all - no need for re-writing framework code .

Translate property name in error messages with FluentValidation

I use FluentValidation in my project in order to validate almost every requests coming into my WebApi.
It works fine, but I've been asked to translate property names in the error messages. My projet must handle at least french and english, so for example, what I want to achieve is :
'First Name' is required (english case)
'Prénom' est requis (french case)
I already have a IPropertyLabelService for other purposes, that is injected in the Startup.cs, that I want to use. It finds translations of property names in a .json, which already works fine.
My problem is that I don't know how to use it globally. I know that FluentValidation's doc says to set the ValidatorOptions.DisplayNameResolver in the Startup file, like this :
FluentValidation.ValidatorOptions.DisplayNameResolver = (type, memberInfo, expression) => {
// Do something
};
I don't know how I can use my IPropertyLabelService inside this, as the Startup.ConfigureServices method is not over yet, so I can't resolve my service...
Any other solution to achieve this behaviour is also more than welcome. I considered using .WithMessage() or .WithName() but I have a really big amount of validators, that would be really long to add this to all individually.
I answered this over on the FluentValidation issue tracker, but for completeness will include the answer here too:
Ssetting FluentValidation.ValidatorOptions.Global.DisplayNameResolver is the correct way to handle this globally (or you can use WithName at the individual rule level).
You need to ensure that this is set once, globally. If you need the service provider to have been initialized first, then make sure you call it at a point after the service provider has been configured (but ensure you still only set it once).
The "options" configuration mechanism in .NET Core allows you to defer configuration until after the point services have been constructed, so you can create a class that implements IConfigureOptions, which will be instantiated and executed during the configuration phase for a particular options type. FluentValidation doesn't provide any options configuration itself, so you can just hook into one of the built-in options classes (ASP.NET's MvcOptions is probably the simplest, but you can also use a different one if you're not using mvc).
For example, you could do something like this inside your ConfigureServices method:
public void ConfigureServices(IServiceCollection services) {
// ... your normal configuration ...
services.AddMvc().AddFluentValidation();
// Afterwards define some deferred configuration:
services.AddSingleton<IConfigureOptions<MvcOptions>, DeferredConfiguration>();
}
// And here's the configuration class. You can inject any services you need in its constructor as with any other DI-enabled service. Make sure your IPropertyLabelService is registered as a singleton.
public class DeferredConfiguration : IConfigureOptions<MvcOptions> {
private IPropertyLabelService _labelService;
public DeferredConfiguration(IPropertyLabelService labelService) {
_labelService = labelService;
}
public void Configure(MvcOptions options) {
FluentValidation.ValidatorOptions.Global.DisplayNameResolver = (type, memberInfo, expression) => {
return _labelService.GetPropertyOrWhatever(memberInfo.Name);
};
}
}

Invalidating Cached Data and Dependency Injection Pattern

I have a data cache class (that uses the MemoryCache class).
The basic function of this class is to cache reference data. To get this reference data it needs an instance of an Entity Framework dbContext. This gets passed in by dependency injection (Simple Injector).
But this dbContext has a lifecycle of "per call" (AsyncScopedLifestyle). So to satisify this I put the call to setup the cache in a "scope" that expires after the call.
The cache gets invalidated every 2 hours and is re-queried. Unsurprisingly, the dbContext has been cleaned up by then (because it went out of the scope).
I can think of ways to get around this issue. But I want to know if there is a pattern I should be following for this kind of issue. (Most of my solutions have me passing the container into my cache class. But that seems to be a violation of several DI patterns.)
Anyone know of a design pattern to use when you have a reoccurring need for an injection inside of a class?
A bit more background:
My cache class (called DataCache) gets the context from constructor injection.
The call to set it up is made from the Configure method in Startup.cs. This looks like this:
.
using (AsyncScopedLifestyle.BeginScope(container))
{
// Setup the long lived data caching
var dataCache = container.GetInstance<DataCache>();
dataCache.SetupCachedItems();
}
It sets the MemoryCache to expire the data in the cache after two hours. But the injected context is long cleaned up by then.
I see two general solutions here:
Move the cache that the DataCache manages out of that class, in such way that MyCacheClass can become Scoped. This seams a no-brainer as this is likely what MemoryCache is for. Memory cache is likely a Singleton.
Move DataCache into the Composition Root so it can safely depend on the container (or a container abstraction), without falling into Service Locator anti-pattern trap.
The first solution can be applied in multiple ways. Perhaps it's a matter of defining the cache in a static field:
public class DataCache
{
private static ConcurrentDictionary<string, object> cache;
}
And in case you inject MemoryCache as storage provider for your data, it will contain the cache, and the lifestyle of DataCache becomes irrelevant:
public class DataCache
{
public DataCache(MyContext context, IMemoryCache cache)
}
If, however, DataCache needs to be injected into Singleton consumers, it itself needs to be Singleton. This disallows this approach, as MyContext needs to be Scoped, to prevent Captive Dependencies. For that you can use solution 2.
With solution to, you ensure that DataCache is created inside your Composition Root. This forces you to hide DataCache behind an abstraction, e.g. IDataCache. This abstraction can be placed in a location that allows consumers to depend on, while the DataCache implementation will be completely hidden inside the Composition Root. At that location it becomes safe to depend on the DI Container.
// Part of the Composition Root
sealed class DataCache: IDataCache
{
public DataCache(Container container, IMemoryCache cache) ...
public ProductData GetProductByKey(string key)
{
if (key not in cache)
{
using (AsyncScopedLifestyle.BeginScope(this.container))
{
var context = container.GetInstance<MyContext>();
var p = context.Products.SingleOrDefault(p => p.Key == key);
var data = new ProductData(p);
AddProductToCache(key, data);
return data;
}
}
}
}
You should rely on DI the whole way. In other words, if the cache class needs the context, then that's a dependency, and should be injected as such:
public class MyCacheClass
{
private readonly MyContext _context;
public MyCacheClass(MyContext context)
{
_context = context;
}
...
}
That of course assumes the cache class has a scoped lifetime as well, which there's really no reason it shouldn't, since it interacts with scoped dependencies. However, if for some reason you need it to have a singleton lifetime, then you can simply inject IServiceProvider and then create a scope and pull out the context when you need it:
using (var scope = _serviceProvider.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<MyContext>();
// do something with context
}
If you're using a static class, don't.

Container.GetInstance(Type) when using WcfOperationLifestyle throws ActivationException

I have a WebAPI service using SimpleInjector. I have this set up using AsyncScopedLifestyle for my scoped dependencies, and one of these dependencies is my Entity Framework DataContext. Many things in my service depend on the DataContext, and it is generally injected in to my MediatR handlers using constructor injection - this works well. Separately I have a few areas where I need to create an instance of an object given its type (as a string), so I have created a custom activator class (ResolvingActivator) that is configured with a reference to Container.GetInstance(Type):
In my container bootstrap code:
ResolvingActivator.Configure(container.GetInstance);
I can then create objects by using methods such as:
ResolvingActivator.CreateInstance<T>(typeName)
When I'm using WebAPI, the above is working perfectly.
A further part of the project is a legacy API that uses WCF. I have implemented this as a translation layer, where I translate old message formats to new message formats and then dispatch the messages to the Mediator; I then translate the responses (in new format) back to old format and return those to the caller. Because I need access to the Mediator in my WCF services, I'm injecting this in their constructors, and using the SimpleInjector.Integration.Wcf package to let SimpleInjector's supplied SimpleInjectorServiceHostFactory build instances of the services. I've also created a hybrid lifestyle, so I can use the same container for my both my WebAPI and WCF services:
container.Options.DefaultScopedLifestyle = Lifestyle.CreateHybrid(
new AsyncScopedLifestyle(),
new WcfOperationLifestyle());
This works well for some calls, but when a call ultimately calls my ResolvingActivator class, I get an ActivationException thrown, with the following message:
The DataContext is registered as 'Hybrid Async Scoped / WCF Operation' lifestyle, but the instance is requested outside the context of an active (Hybrid Async Scoped / WCF Operation) scope.
As I only receive this error when making WCF calls, I'm wondering if I have something wrong in my configuration. In a nutshell, this will work:
public class SomeClass
{
private readonly DataContext db;
public SomeClass(DataContext db)
{
this.db = db;
}
public bool SomeMethod() => this.db.Table.Any();
}
But this will not:
public class SomeClass
{
public bool SomeMethod()
{
// Code behind is calling container.GetInstance(typeof(DataContext))
var db = ResolvingActivator.CreateInstance<DataContext>();
return db.Table.Any();
}
}
Any ideas where I'm going wrong?
Edit: here is the stack trace from the ActivationException:
at SimpleInjector.Scope.GetScopelessInstance[TImplementation](ScopedRegistration`1 registration)
at SimpleInjector.Scope.GetInstance[TImplementation](ScopedRegistration`1 registration, Scope scope)
at SimpleInjector.Advanced.Internal.LazyScopedRegistration`1.GetInstance(Scope scope)
at lambda_method(Closure )
at SimpleInjector.InstanceProducer.GetInstance()
at SimpleInjector.Container.GetInstance(Type serviceType)
at Service.Core.ResolvingActivator.CreateInstance(Type type) in Service.Core\ResolvingActivator.cs:line 43
at Service.Core.ResolvingActivator.CreateInstance(String typeName) in Service.Core\ResolvingActivator.cs:line 35
at Service.Core.ResolvingActivator.CreateInstance[TService](String typeName) in Service.Core\ResolvingActivator.cs:line 69
With a full stack trace here: https://pastebin.com/0WkyHGKv
After close inspection of the stack trace, I can conclude what's going on: async.
The WcfOperationLifestyle under the covers depends on WCF's OperationContext.Current property, but this property has a thread-affinity and doesn't flow with async operations. This is something that has to be fixed in the integration library for Simple Injector; it simply doesn't support async at the moment.
Instead, wrap a decorator around your handlers that start and end a new async scope. This prevents you from having to use the WcfOperationLifestyle all together. Take a look at the ThreadScopedCommandHandlerProxy<T> implementation here to get an idea how to do this (but use AsyncScopedLifestyle instead).

How to Solve Circular Dependency

Hi I have a problem with the structure of my code, it somehow goes into Circular Dependency. Here is an explanation of how my code looks like:
I have a ProjectA contains BaseProcessor and BaseProcessor has a reference to a class called Structure in ProjectB. Inside BaseProcessor, there is an instance of Structure as a variable.
In projectB there are someother classes such as Pricing, Transaction etc.
Every class in ProjectB has a base class called BaseStructure i.e. Structure, Pricing and Transaction classes all inherited from BaseStructure.
Now in Pricing and Transaction classes, I want to call a method in BaseProcessor class from BaseStructure class which causing Circular Dependency.
What I have tried is:
Using Unity, but I didn't figure out how to make it work because I try to use function like:
unityContainer.ReferenceType(IBaseProcessor, BaseProcessor)
in BaseStructure then it will need a reference of BaseProcessor which also cause Circular Dependency.
And I've also tried creating an interface of IBaseProcessor and create a function(the function I want to call) declaration in this interface. And let both BaseProcessor and BaseStructure inherit this interface. But how can I call the function in Pricing and Transaction class without create an instance of BaseProcessor?
Can anyone please tell me how to resolve this problem other than using reflection?
Any help will be much appreciated. Thanks :)
You could use the lazy resolution:
public class Pricing {
private Lazy<BaseProcessor> proc;
public Pricing(Lazy<BaseProcessor> proc) {
this.proc = proc;
}
void Foo() {
this.proc.Value.DoSomethin();
}
}
Note that you haven't to register the Lazy because Unity will resolve it by BaseProcessor registration.
Your DI container can't help solving the circular reference, since it is the dependency structure of the application that prevents objects from being created. Even without a DI container, you can't construct your object graphs without some special 'tricks'.
Do note that in most cases cyclic dependency graphs are a sign of a design flaw in your application, so you might want to consider taking a very close look at your design and see if this can't be solved by extracting logic into separate classes.
But if this is not an option, there are basically two ways of resolving this cyclic dependency graph. Either you need to fallback to property injection, or need to postpone resolving the component with a factory, Func<T>, or like #onof proposed with a Lazy<T>.
Within these two flavors, there are a lot of possible ways to do this, for instance by falling back to property injection into your application (excuse my C#):
public class BaseStructure {
public BaseStructure(IDependency d1) { ... }
// Break the dependency cycle using a property
public IBaseProcessor Processor { get; set; }
}
This moves the IBaseProcessor dependency from the constructor to a property and allows you to set it after the graph is constructed. Here's an example of an object graph that is built manually:
var structure = new Structure(new SomeDependency());
var processor = new BaseProcessor(structure);
// Set the property after the graph has been constructed.
structure.Processor = processor;
A better option is to hide the property inside your Composition Root. This makes your application design cleaner, since you can keep using constructor injection. Example:
public class BaseStructure {
// vanilla constructor injection here
public BaseStructure(IDependency d1, IBaseProcessor processor) { ... }
}
// Defined inside your Composition Root.
private class CyclicDependencyBreakingProcessor : IBaseProcessor {
public IBaseProcessor WrappedProcessor { get; set; }
void IBaseProcessor.TheMethod() {
// forward the call to the real processor.
this.WrappedProcessor.TheMethod();
}
}
Now instead of injecting the BaseProcessor into your Structure, you inject the CyclicDependencyBreakingProcessor, which will be further initialized after the construction of the graph:
var cyclicBreaker = new CyclicDependencyBreakingProcessor();
var processor = new BaseProcessor(new Structure(new SomeDependency(), cyclicBreaker));
// Set the property after the graph has been constructed.
cyclicBreaker.WrappedProcessor = processor;
This is basically the same as before, but now the application stays oblivious from the fact that there is a cyclic dependency that needed to be broken.
Instead of using property injection, you can also use Lazy<T>, but just as with the property injection, it is best to hide this implementation detail inside your Composition Root, and don't let Lazy<T> values leak into your application, since this just adds noise to your application, which makes your code more complex and harder to test. Besides, the application shouldn't care that the dependency injection is delayed. Just as with Func<T> (and IEnumerable<T>), when injecting a Lazy<T> the dependency is defined with a particular implementation in mind and we're leaking implementation details. So it's better to do the following:
public class BaseStructure {
// vanilla constructor injection here
public BaseStructure(IDependency d1, IBaseProcessor processor) { ... }
}
// Defined inside your Composition Root.
public class CyclicDependencyBreakingProcessor : IBaseProcessor {
public CyclicDependencyBreakingBaseProcessor(Lazy<IBaseProcessor> processor) {...}
void IBaseProcessor.TheMethod() {
this.processor.Value.TheMethod();
}
}
With the following wiring:
IBaseProcessor value = null;
var cyclicBreaker = new CyclicDependencyBreakingProcessor(
new Lazy<IBaseProcessor>(() => value));
var processor = new BaseProcessor(new Structure(new SomeDependency(), cyclicBreaker));
// Set the value after the graph has been constructed.
value = processor;
Up until now I only showed how to build up the object graph manually. When doing this using a DI container, you usually want to let the DI container build up the complete graph for you, since this yields a more maintainable Composition Root. But this can make it a bit more tricky to break the cyclic dependencies. In most cases the trick is to register the component that you want to break with a caching lifestyle (basically anything else than transient). Per Web Request Lifestyle for instance. This allows you to get the same instance in a lazy fashion.
Using the last CyclicDependencyBreakingProcessor example, we can create the following Unity registration:
container.Register<BaseProcessor>(new PerRequestLifetimeManager());
container.RegisterType<IStructure, Structure>();
container.RegisterType<IDependency, SomeDependenc>();
container.Register<IBaseProcessor>(new InjectionFactory(c =>
new CyclicDependencyBreakingProcessor(
new Lazy<IBaseProcessor>(() => c.GetInstance<BaseProcessor>())));