Autofac Lifetime Management - asp.net-mvc

I'm working on an ASP.NET MVC project that support external plugins, now, I'm moving from Unity to Autofac and I need to wrap the lifetime objects of Autofac so the plugins won't have to reference it, in Unity I could do something this.
public sealed class UnityScopeFactory : IDependencyScopeFactory
{
private HttpRequestScope _httpRequest;
private SingletonScope _singleton;
private TransientScope _transient;
public IDependencyScope HttpRequest()
{
return _httpRequest ?? (_httpRequest = new HttpRequestScope());
}
public IDependencyScope Singleton()
{
return _singleton ?? (_singleton = new SingletonScope());
}
public IDependencyScope Transient()
{
return _transient ?? (_transient = new TransientScope());
}
private class HttpRequestScope : IDependencyScope
{
public object CreateScope()
{
return new HttpPerRequestLifetimeManager();
}
}
private class SingletonScope : IDependencyScope
{
public object CreateScope()
{
return new ContainerControlledLifetimeManager();
}
}
private class TransientScope : IDependencyScope
{
public object CreateScope()
{
return new TransientLifetimeManager();
}
}
}
I made similar thing in Autofac but I'm not sure whether it's the correct way to do that, I looked into the RegistrationBuilder of Autofac which is (unfortunately) internal and I came up with this.
public class AutofacScopeFactory : IDependencyScopeFactory
{
private HttpRequestScope _httpRequest;
private SingletonScope _singleton;
private TransientScope _transient;
public IDependencyScope HttpRequest()
{
return _httpRequest ?? (_httpRequest = new HttpRequestScope());
}
public IDependencyScope Singleton()
{
return _singleton ?? (_singleton = new SingletonScope());
}
public IDependencyScope Transient()
{
return _transient ?? (_transient = new TransientScope());
}
private class HttpRequestScope : IDependencyScope
{
public object CreateScope()
{
return new CurrentScopeLifetime();
}
}
private class SingletonScope : IDependencyScope
{
public object CreateScope()
{
return new RootScopeLifetime();
}
}
private class TransientScope : IDependencyScope
{
public object CreateScope()
{
return new CurrentScopeLifetime();
}
}
}
Also, after I got this to work, how can I use pass it to the ContainerBuilder?
In Unity I could do something like this.
public sealed class UnityDependencyContainer : IDependencyContainer
{
private readonly IUnityContainer _container;
public UnityDependencyContainer()
{
_container = new UnityContainer()
}
public void Register<TContract, TImplementation>(IDependencyScope scope) where TImplementation : TContract
{
LifetimeManager manager = scope.CreateScope() as LifetimeManager;
if (manager != null)
{
_container.RegisterType<TContract, TImplementation>(manager);
}
}
}
How do I pass an instance of IComponentLifetime to the method chain? is it a dead end?
public class AutofacContainer : IDependencyContainer
{
private static readonly ContainerBuilder Builder;
static AutofacContainer()
{
Builder = new ContainerBuilder();
}
public void RegisterType<TContract, TImplementation>(IDependencyScope scope) where TImplementation : TContract
{
IComponentLifetime manager = scope.CreateScope() as IComponentLifetime;
if (manager != null)
{
Builder.RegisterType<TImplementation>().As<TContract>();
}
}
}

Autofac doesn't separate scopes quite the way you have it outlined, so you might be trying to fit a square peg in a round hole.
Autofac scopes are more hierarchical. Any lifetime scope can spawn a child transient scope. For example, you might see...
Container/root lifetime
HttpRequest scope
Small task-specific transient scope
You can "tag" a scope and register components to a specific named/tagged scope - that's how the HttpRequest scope works. It gets "tagged" with a special identifier.
When you resolve objects is when it determines which lifetime scope owns it. Resolving happens from the most-nested scope. In the above hierarchy, you resolve items from the small task-specific transient scope whether they're singletons, request scoped, or whatever. When the singleton gets resolved, it will search up the lifetime scope stack and automatically assign "ownership" of the object to the root lifetime scope. When a per-request item gets resolved, it searches up the stack for the lifetime scope with the special "HTTP request" identifier and assigns ownership there. Factory-scoped items are resolved in the current lifetime scope.
Note: That discussion is a gross oversimplification of how it works. There is documentation explaining the lifetime scope mechanism on the Autofac site.
Point being, I see some things in the above design that don't really "jive" with the way Autofac does stuff.
The DependencyScopeFactory can't create its own transient or HttpRequest scopes. There are specific lifetime management components that start and end the HttpRequest scope, so you'd need to use those; there is no 'global' transient scope, so you can't really just create one.
HttpRequest scope, assuming you're using MVC, would look more like...
public ILifetimeScope HttpRequestScope
{
get { return AutofacDependencyResolver.Current.RequestLifetime; }
}
There's no analog for a transient scope because usage on that is supposed to be inline:
using(var transientScope = parentScope.BeginLifetimeScope())
{
// Do stuff and resolve dependencies using the transient scope.
// The IDisposable pattern here is important so transient
// dependencies will be properly disposed at the end of the scope.
}
When you register components, you don't register them "into a lifetime scope." You actually register them into a component registry and part of the component registration includes the ownership information about the lifetime of the component once it's resolved.
var builder = new ContainerBuilder();
// This component is factory-scoped and will be "owned" by whatever
// lifetime scope resolves it. You can resolve multiple of these
// in a single scope:
builder.RegisterType<FirstComponent>().As<ISomeInterface>();
// This component is a singleton inside any given lifetime scope,
// but if you have a hierarchy of scopes, you'll get one in each
// level of the hierarchy.
builder.RegisterType<SecondComponent>().InstancePerLifetimeScope();
// This component will be a singleton inside a specifically named
// lifetime scope. If you try to resolve it in a scope without that
// name, it'll search up the scope stack until it finds the scope
// with the right name. If no matching scope is found - exception.
builder.RegisterType<ThirdComponent>().InstancePerMatchingLifetimeScope("scopename");
// This is a per-HTTP-request component. It's just like the
// above InstancePerMatchingLifetimeScope, but it has a special
// tag that the web integration knows about.
builder.RegisterType<FourthComponent>().InstancePerHttpRequest();
If you're trying to make a container/registration agnostic interface, it wouldn't need a "lifetime scope manager" - instead, you'd need to pass some parameters indicating the intended lifetime scope and do the appropriate registration syntax (above) based on the incoming parameters.
Again, I'd recommend you check out that documentation.
Also, if you're using Unity, Autofac does have an Enterprise Library Configurator package that allows you to configure Autofac in a Unity style (since that's how EntLib likes to do things). That might be something to check out.
If you don't need to use Unity syntax at all... I'd recommend just moving to do things the native Autofac way. Trying to make one container look and act like another is a pretty painful endeavor.
Assuming your plugins are in separate assemblies or whatever, you could easily take advantage of some of the nice assembly-scanning syntax along with Autofac modules and hook up your plugins that way.

Related

How to dynamically instantiate a proxy class?

I have used Castle.DynamicProxy to create an interceptor that implements IInterceptor. This interceptor does some work related with logging.
I have successfully injected this into multiple classes using the default Microsoft Dependency Injection and I also was able to do so using Autofac.
Microsoft Dependency Injection:
public static void AddLoggedScoped<TService, TImplementation>(this IServiceCollection pServices)
where TService : class
where TImplementation : class, TService
{
pServices.TryAddScoped<IProxyGenerator, ProxyGenerator>();
pServices.AddScoped<TImplementation>();
pServices.TryAddTransient<LoggingInterceptor>();
pServices.AddScoped(provider =>
{
var proxyGenerator = provider.GetRequiredService<IProxyGenerator>();
var service = provider.GetRequiredService<TImplementation>();
var interceptor = provider.GetRequiredService<LoggingInterceptor>();
return proxyGenerator.CreateInterfaceProxyWithTarget<TService>(service, interceptor);
});
}
Autofac Dependency Injection:
builder.RegisterType<DITest>( ).As<IDITest>()
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(LoggingInterceptorAdapter<LoggingInterceptor>));
Despite this I would also like to inject it in classes dynamically instantiated (for instances, classes that are instantiated accordingly to a value - factory pattern). My factory instantiates different concretizations of an interface depending on a value provided by parameter. Something along these lines:
public IApple Create(string color)
{
IApple fruit;
switch (color)
{
case "green":
fruit = new GreenApple();
break;
case "red":
fruit = new RedApple();
}
return fruit;
}
The interface IFruit looks like these:
public interface IFruit
{
void Cut();
void Eat();
string GetNutrionalInfo();
}
What I am trying to achieve is a way to inject/add an interceptor to the concretization of RedApple() that would allow me to know when methods such as redApple.Cut() are called.
What is the best way to do so? I was under the impression that Autofac would allow this, but I have not been successful.
What you will need to do is update your factory to use service location instead of directly constructing things. Basically, instead of using new, you'll need to use Autofac or Microsoft DI (assuming Autofac is configured as the backing container) to resolve the thing.
First, whenever you need your factory, make sure you are injecting it and not just calling new. Everything involved in this chain needs to go through Autofac.
public class UsesTheFactory
{
private IFactory _factory;
public UsesTheFactory(IFactory factory)
{
this._factory = factory;
}
}
You will, of course, need to register the thing that uses the factory.
builder.RegisterType<UsesTheFactory>();
Next, inject the lifetime scope into the factory and use it for service location. This is how you get the proxy and all that into the created objects.
public class MyFactory : IFactory
{
private readonly ILifetimeScope _scope;
public MyFactory(ILifetimeScope scope)
{
this._scope = scope;
}
public IApple Create(string color)
{
IApple fruit;
switch (color)
{
case "green":
fruit = this._scope.Resolve<GreenApple>();
break;
case "red":
fruit = this._scope.Resolve<RedApple>();
}
return fruit;
}
}
You'll need to register the factory and the things that the factory needs to resolve.
builder.RegisterType<MyFactory>().As<IFactory>();
builder.RegisterType<RedApple>();
builder.RegisterType<GreenApple>();
Finally, whenever you need something that uses the factory, that thing needs to be resolved. In this example, you can't really ever just new UsesTheFactory() - you have to resolve it (or have it injected into something else).
var builder = new ContainerBuilder();
builder.RegisterType<UsesTheFactory>();
builder.RegisterType<MyFactory>().As<IFactory>();
builder.RegisterType<RedApple>();
builder.RegisterType<GreenApple>();
var container = builder.Build();
using var scope = container.BeginLifetimeScope();
var user = scope.Resolve<UsesTheFactory>();
user.DoSomethingThatCallsTheFactory();
The key principle is that if you need that proxy injected anywhere in the pipeline, you can't use new. Full stop. If you need that thing, it needs to flow through Autofac somehow.

How to access a DurableEntityClient in an injected class with Azure Durable Functions

I have an Azure Functions project that leverages Dependency Injection (Startup.cs injects services based on the different interfaces). Those services that implement the interfaces are using constructor dependency injection as well.
In one of those implementations, I want to call a method on a Durable Entity, but I prefer not to make the DurableEntityClient part of the method signature (as other implementations might not need the EntityClient at all). So therefore, I was hoping to see that IDurableEntityClient injected in the constructor of my class.
But it turns out the value is null. Wondering if this is something that is supported and feasible? (to have a DI-friendly way of injecting classes that want to get the EntityClient for the Functions runtime they are running in)
Some code snippets:
Startup.cs
builder.Services.AddSingleton<IReceiver, TableReceiver>();
Actual Function
public class ItemWatchHttpTrigger
{
private IReceiver _receiver;
public ItemWatchHttpTrigger(IReceiver receiver)
{
_receiver = receiver;
}
[FunctionName("item-watcher")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "item/{itemId}")]
HttpRequest request, string itemId, [DurableClient] IDurableEntityClient client, ILogger logger)
{
// Actual implementation
}
}
Referenced class
public class TableReceiver : IReceiver
{
private IDurableEntityClient _entityClient;
public TableReceiver(IDurableEntityClient client)
{
_entityClient = client; // client is null :(
}
}
Based on the answer of my github issue, it seems it is possible to inject this in Startup, since the 2.4.0 version of the Microsoft.Azure.WebJobs.Extensions.DurableTask package:
Some code snippets:
Startup.cs
builder.Services.AddSingleton<IReceiver, TableReceiver>();
builder.Services.AddDurableClientFactory();
Referenced class
public class TableReceiver : IReceiver
{
private IDurableEntityClient _entityClient;
public TableReceiver(IDurableClientFactory entityClientFactory, IConfiguration configuration)
{
_entityClient = entityClientFactory.CreateClient(new DurableClientOptions
{
TaskHub = configuration["TaskHubName"]
});
}
}
Github issue

How do you add a runtime string parameter into a dependency resolution chain?

How could I setup my chosen DI for this kind of setup:
public abstract class BaseRepo
{
public BaseRepo(string token)
{
}
}
public RepoA : BaseRepo, IRepoA
{
// implementation of interface here
}
public ViewModelA
{
IRepoA _repo;
public ViewModelA(IRepoA repo)
{
this._repo = repo;
}
public DoMethod()
{
this._repo.DoSomeStuff();
}
}
In real scenario, the token parameter on the base class is resolved after the user has been logged in. I was thinking of just configuring the interfaces for DI after the login but I'm not sure if that a right thing do.
I looked at some Factories but I can't make it to work.
My choice of DI probably goes to AutoFac/Ninject and the project is Xamarin mobile app
In real scenario, the token parameter on the base class is resolved
after the user has been logged in.
This means that the token parameter is runtime data. Prevent injecting runtime data into your components. Your components should be stateless. Instead, runtime data should be passed on through method calls through the previously constructed object graph of components. Failing to do so, will make it much more complicated to configure and verify your object graphs.
There are typically to ways of passing runtime data. Either you pass it on through method calls from method to method through the object graph, or your components call a method that returns that correct value. This token seems like it is contextual information and that would typically mean you choose the latter option:
public interface ITokenProvider {
string GetCurrentToken();
}
// Don't use base classes: base classes are a design smell!
public RepoA : IRepoA
{
private readonly ITokenProvider tokenProvider;
public RepoA(ITokenProvider tokenProvider) {
this.tokenProvider = tokenProvider;
}
// IRepoA methods
public A GetById(Guid id) {
// Get token at runtime
string token = this.tokenProvider.GetCurrentToken();
// Use token here.
}
}
In your Composition Root, you will have to create an implementation for this ITokenProvider. How this implementation looks is highly dependent on how you wish to store this token, but here's a possible implementation:
public sealed class AspNetSessionTokenProvider : ITokenProvider {
public string GetCurrentToken() {
return (string)HttpContext.Current.Session["token"];
}
}

Autofac get decorated QueryHandler by convention based on constructor parameter name?

We inject IQueryHandler<TQUery,TResult> into our MVC controllers. We globally register all of these in the container
We have written a decorator that can cache the results of IQueryHandler.
We want to sometimes get cached reults and other times not from the same handler.
Is it possible to conditionally get a decorated handler based on the name of the constructor parameter. e.g. inject IQueryHandler<UnemployedQuery, IEnumerable<People>> cachedPeopleHandler if we prefix constructor parameter name with cached we actually get it wrapped with decorator?
Just trying to use a more convention over configuration approach to simplify things.
Yes it's possible to do it. Below is a simple working example on how you can achieve it:
class Program
{
public interface IQueryHandler{}
private class QueryHandler : IQueryHandler
{
}
private class CacheQueryHandler : IQueryHandler
{
}
public interface IService
{
}
private class Service : IService
{
private readonly IQueryHandler _queryHandler;
private readonly IQueryHandler _cacheQueryHandler;
public Service(IQueryHandler queryHandler, IQueryHandler cacheQueryHandler)
{
_queryHandler = queryHandler;
_cacheQueryHandler = cacheQueryHandler;
}
public override string ToString()
{
return string.Format("_queryHandler is {0}; _cacheQueryHandler is {1}", _queryHandler,
_cacheQueryHandler);
}
}
static void Main(string[] args)
{
var builder = new ContainerBuilder();
// Register the dependency
builder.RegisterType<QueryHandler>().As<IQueryHandler>();
// Register the decorator of the dependency
builder.RegisterType<CacheQueryHandler>().Keyed<IQueryHandler>("cache");
// Register the service implementation
builder.RegisterType<Service>().AsSelf();
// Register the interface of the service
builder.Register(c =>
{
var ctor = typeof (Service).GetConstructors()[0];
var parameters =
ctor.GetParameters()
.Where(p => p.Name.StartsWith("cache"))
.Select(p => new NamedParameter(p.Name, c.ResolveKeyed("cache", p.ParameterType)));
return c.Resolve<Service>(parameters);
}).As<IService>();
using (var container = builder.Build())
{
var service = container.Resolve<IService>();
Console.WriteLine(service.ToString());
Console.ReadKey();
}
}
}
Update:
Basically you need to:
1. Think up a general convention. Prefix "cache" of ctor parameter name in your case.
2. Register your dependencies as usual.
3. Register your decorators, so they don't overwrite your original dependencies and you can easily resolve them basing on your convention. e.g. Keyed, Named, via Attribute, etc.
4. Register you actual implementation of class that uses decorators
5. Register your interface that describes the class via lambda expression that has all magic inside.
Note: I provided just a simple and working example. It's on you to make it nice, easy to use and fast e.g. make it as an extension, generic, cache reflection results etc. It's not difficult anyway.
Thanks.

How do I handle classes with static methods with Ninject?

How do I handle classes with static methods with Ninject?
That is, in C# one can not have static methods in an interface, and Ninject works on the basis of using interfaces?
My use case is a class that I would like it to have a static method to create an
unpopulated instance of itself.
EDIT 1
Just to add an example in the TopologyImp class, in the GetRootNodes() method, how would I create some iNode classes to return? Would I construct these with normal code practice or would I somehow use Ninject? But if I use the container to create then haven't I given this library knowledge of the IOC then?
public interface ITopology
{
List<INode> GetRootNodes();
}
public class TopologyImp : ITopology
{
public List<INode> GetRootNodes()
{
List<INode> result = new List<INode>();
// Need code here to create some instances, but how to without knowledge of the container?
// e.g. want to create a few INode instances and add them to the list and then return the list
}
}
public interface INode
{
// Parameters
long Id { get; set; }
string Name { get; set; }
}
class NodeImp : INode
{
public long Id
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public string Name
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
}
// Just background to highlight the fact I'm using Ninject fine to inject ITopology
public partial class Form1 : Form
{
private ITopology _top;
public Form1()
{
IKernel kernal = new StandardKernel(new TopologyModule());
_top = kernal.Get<ITopology>();
InitializeComponent();
}
}
If you're building a singleton or something of that nature and trying to inject dependencies, typically you instead write your code as a normal class, without trying to put in lots of (probably incorrect) code managing the singleton and instead register the object InSingletonScope (v2 - you didnt mention your Ninject version). Each time you do that, you have one less class that doesnt surface its dependencies.
If you're feeling especially bloody-minded and are certain that you want to go against that general flow, the main tools Ninject gives you is Kernel.Inject, which one can use after you (or someone else) has newd up an instance to inject the dependencies. But then to locate one's Kernelm you're typically going to be using a Service Locator, which is likely to cause as much of a mess as it is likely to solve.
EDIT: Thanks for following up - I see what you're after. Here's a hacky way to approximate the autofac automatic factory mechanism :-
/// <summary>
/// Ugly example of a not-very-automatic factory in Ninject
/// </summary>
class AutomaticFactoriesInNinject
{
class Node
{
}
class NodeFactory
{
public NodeFactory( Func<Node> createNode )
{
_createNode = createNode;
}
Func<Node> _createNode;
public Node GenerateTree()
{
return _createNode();
}
}
internal class Module : NinjectModule
{
public override void Load()
{
Bind<Func<Node>>().ToMethod( context => () => Kernel.Get<Node>() );
}
}
[Fact]
public void CanGenerate()
{
var kernel = new StandardKernel( new Module() );
var result = kernel.Get<NodeFactory>().GenerateTree();
Assert.IsType<Node>( result );
}
}
The ToMethod stuff is a specific application of the ToProvider pattern -- here's how you'd do the same thing via that route:-
...
class NodeProvider : IProvider
{
public Type Type
{
get { return typeof(Node); }
}
public object Create( IContext context )
{
return context.Kernel.Get<Node>();
}
}
internal class Module : NinjectModule
{
public override void Load()
{
Bind<Func<Node>>().ToProvider<NodeProvider>();
}
}
...
I have not thought this through though and am not recommending this as A Good Idea - there may be far better ways of structuring something like this. #Mark Seemann? :P
I believe Unity and MEF also support things in this direction (keywords: automatic factory, Func)
EDIT 2: Shorter syntax if you're willing to use container-specific attributes and drop to property injection (even if Ninject allows you to override the specific attributes, I much prefer constructor injection):
class NodeFactory
{
[Inject]
public Func<Node> NodeFactory { private get; set; }
public Node GenerateTree()
{
return NodeFactory();
}
}
EDIT 3: You also need to be aware of this Ninject Module by #Remo Gloor which is slated to be in the 2.4 release
EDIT 4: Also overlapping, but not directly relevant is the fact that in Ninject, you can request an IKernel in your ctor/properties and have that injected (but that doesn't work directly in a static method).

Resources