CastleWindsor BeginScope analog in Ninject - ninject

I am using Scoped lifestyle for some dependencies in code with CastleWindsor and resolving them in scope like this:
using (_container.BeginScope())
{
_implementation = _container.Resolve<IAbstration>();
}
Does Ninject have analogs of such behavior?

There is nothing built-in, but you can easily add this feature by creating a custom class that inherits from DisposableObject:
sealed class Scope : DisposableObject { }
You will have to store Scope instances on the active thread or async context, for instance using AsyncLocal<T>:
static readonly AsyncLocal<Scope> scopeProvider = new AsyncLocal<Scope>();
Now you can create your custom BeginScope() method that uses the scopeProvider as follows:
static Scope BeginScope() => scopeProvider.Value = new Scope();
Now you can implement your use case:
using (BeginScope())
{
_implementation = _kernel.Get<IAbstration>();
}
Registering scoped instances can be done using the InScope method:
static Scope RequestScope(IContext context) => scopeProvider.Value;
void Configure()
{
IKernelConfiguration config = new KernelConfiguration();
config.Bind<IUserService>().To<AspNetUserService>().InScope(RequestScope);
}

Related

Creating Singleton CacheManager in Asp.Net Core

I am trying to create Singleton CacheManager class that has dependency on IMemoryCache.
public class CacheManager:ICacheManager
{
private readonly IMemoryCache _cache;
public CacheManager(IMemoryCache cache)
{
_cache = cache;
}
public void LoadCache(MyData data)
{
// load cache here at startup from DB
}
}
I also have a Scoped service that retrives data from the database
public class LookupService:ILookupService
{
private readonly MyDatabaseContext _dbContext;
public class LookupService(MyDatabaseContext dbContext)
{
_dbContext = dbContext;
}
public void Dispose()
{
//Dispose DBContext here
}
// some async methods that returns lookup collection
}
Register these services in Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// EF
services.AddDbContext<MyDatabaseContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
// domain services
services.AddScoped<ILookupService, LookupService>();
services.AddMemoryCache();
// singleton
services.AddSingleton<CacheManager>(sp=>
{
using(var scope = sp.CreateScope())
{
using (var service = scope.ServiceProvider.GetService<ILookupService>())
{
how do i create cacheManager instance by injecting IMemoryCache and also register callback function
}
}
});
}
ILookupService is registered as Scoped service becuase it has dependency on DBContext which is also (by default) registered with Scoped lifetime. I do not want to change lifetime of these services.
However I want CacheManager to be registered as Singleton, that means I cannot inject ILookupService as dependency into CacheManager.
So here is my possible solution to create & register singleton instance of CacheManager
services.AddSingleton<CacheManager>(sp=>
{
using(var scope = sp.CreateScope())
{
using (var lookupService = scope.ServiceProvider.GetService<ILookupService>())
{
var cache = scope.ServiceProvider.GetService<IMemoryCache>();
var manger = new CacheManager(cache);
manger.LoadCache(lookupService.GetData());
return manger;
}
}
});
Not sure this is the best way to create CacheManager. How do I implement a callback function to re-populate CacheEntry if it becomes null?
I guess I would simply configure services.AddSingleton<CacheManager>();
(CacheManager having a default constructor)
After configuring all of the DI dependencies and having a serviceprovider, get the Cachemanager singleton and initialize it with LoadCache.
(so let DI create "empty" singleton cachemanager, but initialize immediately somewhere in startup of application)
var cachemanager = scope.ServiceProvider.Get<CacheManager>();
var lookupService = scope.ServiceProvider.Get<ILookupService>();
var cache = scope.ServiceProvider.Get<IMemoryCache>();
cachemanager.Cache = cache;
cachemanager.LoadCache(lookupService.GetData());
Looks like the underlying issue is that ILookupService cannot be resolved until runtime and requests start coming in. You need to create CacheManager before this.
DI COMPOSITION
This should be done when the app starts - as in this class of mine. Note the different lifetimes for different types of object but I just focus on creating the objects rather than interactions.
DI RESOLUTION
.Net uses a container per request pattern where scoped objects are stored against the HttpRequest object. So a singleton basically needs to ask for the current ILookupService, which is done by calling:
container.GetService<ILookupService>
So include the DI container as a constructor argument to your CacheManager class and you will be all set up. This is the service locator pattern and is needed to meet your requirement.
An alternative per request resolution mechanism is via the HttpContext object as in this class, where the following code is used:
IAuthorizer authorizer = (IAuthorizer)this.Context.RequestServices.GetService(typeof(IAuthorizer));
SUMMARY
The important thing is to understand the above design pattern, and you can then apply it to any technology.
register Cache service as singleton, try below code
public class CacheService : ICacheService
{
private ObjectCache _memoryCache;
/// <summary>
/// Initializes a new instance of the <see cref="CacheService"/> class.
/// </summary>
public CacheService()
{
this._memoryCache = System.Runtime.Caching.MemoryCache.Default;
}
}

Mediatr Scope problems

I am using Mediatr to handle messages from a queue. I can get a simple example to work. However I have run into problems when I try to inject an object into my handler
public class MessageCommandHandler : IRequestHandler<MessageCommand, bool>
{
private IMyDependency myDependency;
public MessageCommandHandler(IMyDependency myDependency)
{
this.myDependency = myDependency;
}
public Task<bool> Handle(MessageCommand request, CancellationToken cancellationToken)
{
return Task.FromResult(true);
}
}
This only works when I register IMyDependency as a transient scope, however when I register it as scoped lifetime it fails with the error
Cannot resolve 'MediatR.IRequestHandler`2[MyNamespace.MessageCommand,System.Boolean]' from root provider because it requires scoped service 'MyNamespace.IMyDependency'
I need to be able to inject dependencies with scoped lifetime. Has anyone got a solution for this.
I am using the .NET Core dependency injection framework. It is setup as follows
services.AddHostedService<QueueConsumer>();
services.AddScoped<IMyDependency, MyDependency>();
services.AddMediatR(new Assembly[] { Assembly.GetExecutingAssembly() });
Any ideas?
Any time you use a dependency with a Scoped lifetime, you will need to use it inside a pre-created scope. In the case of MVC this would happen automatically behind the scenes but if you're using direct from your own code, say via a console application or something, you will need to create the scope yourself.
This can be done by injecting an instance of IServiceScopeFactory and then using this factory to create a scope and then retrieve the dependency from that scope e.g.
public class MessageCommandHandler : IRequestHandler<MessageCommand, bool>
{
private IServiceScopeFactory _serviceScopeFactory;
public MessageCommandHandler(IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = serviceScopeFactory;
}
public Task<bool> Handle(MessageCommand request, CancellationToken cancellationToken)
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var scopedServices = scope.ServiceProvider;
var myDependency = scopedServices.GetRequiredService<IMyDependency>();
return Task.FromResult(true);
}
}
}
However (and note that the code above is untested), in my own systems I would almost always create the scope around whatever is sending the mediator request in which case any Scoped dependencies will still be injected automatically at this scope e.g.
... // some other calling class / Main method etc..
using (var scope = _serviceScopeFactory.CreateScope())
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
mediator.Send(new MessageCommand());
}

Custom action filter unity dependency injection web api 2

I followed this article and got everything working except dependency inject (partially). In my project I am using unity and I am trying to create a custom Transaction attribute the purpose of which is to start a NHibernate transaction before the execution of an action and commit/rollback the transaction after the method execution.
This is the definition of my attribute:-
public class TransactionAttribute : Attribute
{
}
Following is the definition of my TransactionFilter
public class TransactionFilter : IActionFilter
{
private readonly IUnitOfWork _unitOfWork;
public TransactionFilter(IUnitOfWork uow) {
_unitOfWork = uow;
}
public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) {
var transAttribute = actionContext.ActionDescriptor.GetCustomAttributes<TransactionAttribute>().SingleOrDefault();
if (transAttribute == null) {
return continuation();
}
var transaction = uow.BeginTransaction();
return continuation().ContinueWith(t =>
{
try{
transaction.Commit();
return t.Result;
}
catch(Exception e)
{
transaction.Rollback();
return new ExceptionResult(ex, actionContext.ControllerContext.Controller as ApiController).ExecuteAsync(cancellationToken).Result;
}
}
}
}
And I have created a custom filter provider which uses unity to construct this filter.
public class UnityActionFilterProvider
: ActionDescriptorFilterProvider,
IFilterProvider
{
private readonly IUnityContainer container;
public UnityActionFilterProvider(IUnityContainer container)
{
this.container = container;
}
public new IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
foreach (IActionFilter actionFilter in container.ResolveAll<IActionFilter>())
{
// TODO: Determine correct FilterScope
yield return new FilterInfo(actionFilter, FilterScope.Global);
}
}
}
I register the UnityActionFilterProvider in UnityWebApiActivator (I am using Unity.AspNet.WebApi package) as follows
public static void Start()
{
var container = UnityConfig.GetConfiguredContainer();
var resolver = new UnityDependencyResolver(container);
var config = GlobalConfiguration.Configuration;
config.DependencyResolver = resolver;
var providers = config.Services.GetFilterProviders();
var defaultProvider = providers.Single(i => i is ActionDescriptorFilterProvider);
config.Services.Remove(typeof(IFilterProvider), defaultProvider);
config.Services.Add(typeof(IFilterProvider), new UnityActionFilterProvider(container));
}
The problem is everything works ok for the first request for any action but subsequent requests for the same action doesn't recreate the TransactionFilter which means it doesn't call the constructor to assign a new UOW. I don't think I can disable the action filter caching.
The only option I have got now is to use the service locator pattern and get UOW instance using container inside ExecuteActionFilterAsync which in my opinion kills the purpose of this and I am better off implementing custom ActionFilterAttribute.
Any suggestions ?
As far as I've been able to tell during the years, what happens in web application startup code essentially has Singleton lifetime. That code only runs once.
This means that there's only a single instance of each of your filters. This is good for performance, but doesn't fit your scenario.
The easiest solution to that problem, although a bit of a leaky abstraction, is to inject an Abstract Factory instead of the dependency itself:
public class TransactionFilter : IActionFilter
{
private readonly IFactory<IUnitOfWork> _unitOfWorkFactory;
public TransactionFilter(IFactory<IUnitOfWork> uowFactory) {
_unitOfWorkFactory = uowFactory;
}
// etc...
Then use the factory in the ExecuteActionFilterAsync method:
var transaction = _unitOfWorkFactory.Create().BeginTransaction();
A more elegant solution, in my opinion, would be to use a Decoraptor that Adapts the TransactionFilter, but the above answer is probably easier to understand.

Singleton with StructureMap custom convention in ASP.NET MVC 4

I am having an issue trying to get the singleton lifecycle to work with a custom convention in StructureMap.
Basically I have a custom registry type class that contains a dictionary that I would like to be a singleton so that it is created once at startup of the application.
I created a custom convention that will look at an attribute of a class and determine whether or not the class should be HttpContextScoped or Singleton.
The problem is that when I run the application with the Visual Studio debugger the constructor of the object that should be a singleton gets called every time the web page is loaded instead of happening once as I expected. It looks like the object is behaving as a HttpContextScoped instead of a Singleton.
Here are some details:
StructuremapMvc class in app_start folder
public static class StructuremapMvc
{
public static void Start()
{
IContainer container = IoC.Initialize();
DependencyResolver.SetResolver(new StructureMapDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new StructureMapDependencyResolver(container);
}
}
Ioc class
public static IContainer Initialize()
ObjectFactory.Initialize(x =>
{
x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.AssemblyContainingType<IConfigManager>();
scan.WithDefaultConventions();
scan.Convention<CustomConvention>();
});
CustomConvention : IRegistrationConvention
public void Process(Type type, Registry registry) public void Process(Type type, Registry registry)
{
var attributes = type.GetCustomAttributes(false);
if (attributes.Length > 0)
{
if (attributes[0] is SingletonAttribute)
{
registry.For(type).Singleton();
}
else if (attributes[0] is HttpContextScopedAttribute)
{
registry.For(type).HttpContextScoped();
}
}
}
[Singleton]
public class MyRegistry : IMyRegistry
This questions seems to be quite old but I'll trie to answer it anyway because there could be others which are experiencing the same problem with Structure map. In some cases singleton insances are created "per instance" referring to the instance where they are injected in. This means that you could have different instances of "singleton" when they are injected somewhere else. I've personally seen this behavior with WEBAPI inside MVC app.
The only way I could make it work as "true" global singleton is by using generic interface with specific type parameters to distinguish different types to be used:
public interface ITest<T>
{
}
public class Test1 : ITest<int>
{
}
public class Test2 : ITest<string>
{
}
Scan(x =>
{
x.TheCallingAssembly();
x.IncludeNamespace("MvcApplication1");
x.ConnectImplementationsToTypesClosing(typeof(ITest<>))
.OnAddedPluginTypes(a => a.LifecycleIs(InstanceScope.Singleton));
});
I know that this isn't as ellegant nor usable as approach described above but at least it works as expected. Other approach which works is to do standard mapping one-on-one like:
For<ISingleton>().Singleton().Use<Singleton>();

Ninject Factory Custom Instance Provider

I'm using the Ninject Factory Extension and creating a custom instance provider explained in the wiki:
class UseFirstArgumentAsNameInstanceProvider : StandardInstanceProvider
{
protected override string GetName(System.Reflection.MethodInfo methodInfo, object[] arguments)
{
return (string)arguments[0];
}
protected override Parameters.ConstructorArgument[] GetConstructorArguments(System.Reflection.MethodInfo methodInfo, object[] arguments)
{
return base.GetConstructorArguments(methodInfo, arguments).Skip(1).ToArray();
}
}
I've defined the following factory interface:
interface IFooFactory
{
IFoo NewFoo(string template);
}
I've created the following bindings:
kernel.Bind<IFooFactory>().ToFactory(() => new UseFirstArgumentAsNameInstanceProvider());
kernel.Bind<IFoo>().To<FooBar>().Named("Foo");
Now when I call the following I will get an instance of FooBar:
var foobar = fooFactory.NewFoo("Foo");
This all works great. What I would like however is something a little more like this:
interface IFooTemplateRepository
{
Template GetTemplate(string template);
}
I have a repository that will bring back a template based on the name ("Foo") and I want to pass the template as a constructor argument.
public class FooBar
{
public FooBar(Template template)
{
}
}
Is this possible? I'm not sure what should have the dependency on ITemplateRepository.
Don't use the IoC container to create instances of entities. This is business logic and therefore it does not belong in the composition root. The correct way to handle this is to use the ORM directly (e.g. with the repository pattern you are using).
var template = this.templateRepository.Get("SomeTemplate");
var fooBar = this.fooBarFactory.CreateFooBar(template);