I have a ICommand interface and tasks that are using dependencies injected by constructor. Dependencies are using different constructors so they have to be resolved by the request itself. I want to tell my container how to resolve some dependencies in the specific context it's being resolved.
interface ICommand
{
string Do();
}
interface IUser
{
string Name { get; }
}
class Welcome : ICommand
{
IUser _user;
public Welcome(IUser user)
{
_user = user;
}
public string Do()
{
return "Hello, "+_user.Name;
}
}
class OAuthUser : IUser
{
// use remote service to get data
public OAuthUser (IOAuthService service, JsonWebToken token)
{
// to be implemented
}
}
class TemporaryTokenUser : IUser
{
// use sql to check if user has temporary token
public TemporaryTokenUser (IDbConnection db, string token)
{
// to be implemented
}
}
class UserPasswordUser : IUser
{
// try authenticating user with credentials
public UserPasswordUser (IAuthService svc, string user, string password)
{
// to be implemented
}
}
I've registered my interfaces and classes in LightInject:
var container = new LightInject.ServiceContainer();
container.Register<ICommand, Welcome>("welcome");
Now, I want to do something like this in my requests:
using (var scope = container.BeginScope())
{
// I need to tell my container how to resolve this dependency in case its needed
// but method below does not exist
scope.ResolverForScope<IUser>(()=>createIUser(request));
var command = container.GetInstance<ICommand>(command);
return command.Do();
}
What would be the correct way to do this in maintainable way with any DI container, considering that dependency chain might get quite long for complex methods?
EDIT
I made my use case more clear (changed classes implementing IUser).
static class ScopedContainerExtensions
{
class ScopedContainer
{
Dictionary<Type, object> factories = new Dictionary<Type,object>();
public void Register<T>(Func<T> factory)
where T: class
{
factories.Add(typeof(T), new Lazy<T>(factory));
}
public T Resolve<T>()
{
return ((Lazy<T>)factories[typeof(T)]).Value;
}
}
public static void UseScopedContainerFor<Service>(this IServiceContainer container)
{
if (!container.CanGetInstance(typeof(ScopedContainer), ""))
{
container.Register<ScopedContainer>(new PerScopeLifetime());
}
container.Register<Service>(sf=>sf.GetInstance<ScopedContainer>().Resolve<Service>());
}
public static void ResolverForCurrentScope<T>(this IServiceContainer container, Func<IServiceFactory, T> factory)
where T : class
{
var scope = container.ScopeManagerProvider.GetScopeManager().CurrentScope;
container.GetInstance<ScopedStorage>().Register<T>(() =>
{
var instance = factory(container);
var disposable = instance as IDisposable;
if (disposable != null)
scope.TrackInstance(disposable);
return instance;
});
}
Registration:
container.UseScopedContainerFor<IUser>();
Usage in scope:
container.ResolverForCurrentScope<IUser>(fac => fac.GetInstance<OAuthUserFactory>().Create(fac.GetInstance<IOAuthService>(), Request));
It might be developed via using the Factory pattern.
With this approach, you might be able to get an instance of the specific user with a Factory to provide instances for each concrete class.
Using explicit service registration:
var container = new LightInject.ServiceContainer();
//register your command passing a user instance
container.Register<ICommand>(factory => new Welcome(factory.GetUser<IUser>(request)));
using (var scope = container.BeginScope())
{
var command = (ICommand)container.GetInstance<ICommand>();
return command.Do();
}
I just referred to LightInject web page. There is a chapter called "Dependency Constructors" for further information. http://www.lightinject.net/#toc16
Hope it helps
Related
I have MemoryCache objects (Application,Configuration etc) which I registered them as Singleton. Also there are scoped repositories which selects data from db to fill cache.
For example here is the Singleton registered class,
public class ApplicationCache : MultipleLoadCache<Application>
{
public ApplicationCache()
{
}
}
MultipleLoadCache overrides the CacheItemPolicy, (there is also SingleLoadCache),
public class MultipleLoadCache<TEntity> : SmartCache<TEntity> where TEntity : class
{
public MultipleLoadCache()
{
}
protected override CacheItemPolicy SetPolicy()
{
return new CacheItemPolicy()
{
AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(15)
};
}
}
And base class is,
public class SmartCache<TEntity> : IDisposable where TEntity : class
{
public bool TryGetList(IRepository<TEntity> repository, out List<TEntity> valueList)
{
valueList = null;
lock (cacheLock)
{
GenerateCacheIfNotExists(repository, out valueList);
if (valueList == null || valueList.Count == 0)
{
valueList = (List<TEntity>)_memoryCache.Get(key);
}
}
return valueList != null;
}
I know that scoped services can't be injected to singleton class. So I prefer to use method injection.
private void GenerateCacheIfNotExists(IRepository<TEntity> repository, out List<TEntity> list)
{
list = null;
if (!_memoryCache.Any(x => x.Key == key)) // if key not exists, get db records from repo.
{
IEnumerable<TEntity> tempList = repository.GetList();
list = tempList.ToList();
_cacheItemPolicy = SetPolicy();
SetCacheList(list);
}
}
}
And at controller I try to get cache values, but this part seems wrong to me. If I try to get cache values, I shouldn't pass repository as parameter.
private readonly ApplicationCache _appCache;
public LogController(ApplicationCache appCache)
{
_appCache = appCache;
}
[HttpPost]
[Route("Register")]
public List<Application> Register([FromServices] IApplicationRepository repository)
{
List<Application> cf;
_appCache.TryGetList(repository, out cf);
return cf;
}
Also, by doing Method Injection. I am also unable to use RemovedCallBack event of CacheItemPolicy. Because, when callback triggers (reload cache), I need repository to get records from db again.
Is this design seems nice, what is the best design to do this by using callback events of MemoryCache?
Update 1-
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddMemoryCache();
services.AddSingleton(x => new ApplicationCache());
services.AddScoped<IApplicationRepository, ApplicationRepository>();
}
Thanks,
I had the same issue. Since static classes is compiled at the beginning it cannot inject the required services later. I figured it out by using IServiceScopeFactory.
You basically inject IServiceScopeFactory serviceScopeFactory in the constructer .
static SampleClass(IServiceScopeFactory serviceScopeFactory){
//serviceScopedFactory will act as Singleton, since it is a static class
_serviceScopeFactory = serviceScopeFactory;
}
And use it like this in the method :
using (var scope = _serviceScopeFactory.CreateScope())
{
var service = scope.ServiceProvider.GetRequiredService<IService>();
//Here you can use the service. This will be used as Scoped since it will be
//recreated everytime it is called
}
I want to give a caller of my class ability to choose provider by name, instead of passing the provider concrete class as standard DI recommends. It will allow to hide actual implementation details from client, still giving control which provider to use. We've done it by implementing factory
public ICurrencyProvider GetCurrencyServiceProvider(string providerName)
{
switch (providerName)
{
case "CurrencyLayerAPI":
{ currencyService = new CurrencyLayerWrapper(); }
break;
case "XE":
{ currencyProvider = new XEWrapper(); }
break;
}
return _currencyProvider;
}
and constuctor expects providerName as a parameter.
However for unit tests I wish to use Substitute, not concrete class of provider.
I ended up with 2 parameters, responsible for the same choice- name for production code and interface for calls from tests.
public CurrencyProcessor(string providerName, ICurrencyProvider substituteCurrencyProvider =null)
{
if(!providerName .IsNullOrEmpty())
{
_currencyProvider = GetCurrencyServiceProvider(providerName);
}
else
{ _currencyProvider =substituteCurrencyProvider;
}
}
Slightly alternative implementation is to read providerName from configuration instead of passing it as a parameter.
public CurrencyProcessor(IConfigurationProvider configurationProvider, ICurrencyProvider substituteCurrencyProvider =null)
{
_providerName = _configurationProvider.GetAppSetting("CurrencyProviderToUse");
if(!providerName .IsNullOrEmpty())
{
_currencyProvider = GetCurrencyServiceProvider(providerName);
}
else
{ _currencyProvider =substituteCurrencyProvider;
}
}
I wander, is any better way exist to have single parameter to control creation of internal object, but avoiding giving responsibility to create object to a client.
Related discussions
How to use Dependency Injection without breaking encapsulation?
Preferable way of making code testable: Dependency injection vs encapsulation
https://softwareengineering.stackexchange.com/questions/344442/dependency-injection-with-default-construction
since in your constructor your are statically creating your provider, just inject the provider.
create a factory as you describe....
public class CurrencyFactory
{
public static ICurrencyProvider GetCurrencyServiceProvider(string providerName)
{
return null;
}
}
then use standard dependency injection :-
public class CurrencyProcessor
{
private ICurrencyProvider _currencyProvider;
public CurrencyProcessor(ICurrencyProvider currencyProvider)
{
_currencyProvider = currencyProvider;
}
}
and then use like so
var p = new CurrencyProcessor(CurrencyFactory.GetCurrencyServiceProvider("bitcoin"));
then in your test mock it
var mock = new Mock<ICurrencyProvider>(). // mock stuff
Not sure if I understand it correct.
For me it sounds like you want to have 2 different Factories.
First create a Interface:
public interface ICurrencyProviderFactory
{
ICurrencyProvider Create()
}
Then create a Configuration Factory:
public class ConfigurationCurrencyProviderFactory : ICurrencyProviderFactory
{
public ConfigurationCurrencyProviderFactory(IConfigurationProvider configuration)
{
}
public ICurrencyProvider Create()
{
}
}
And then a UnitTest Factory:
public class UnitTestCurrencyProviderFactory : ICurrencyProviderFactory
{
public UnitTestCurrencyProviderFactory()
{
}
public ICurrencyProvider Create()
{
}
}
Your currency processor should look like this:
public CurrencyProcessor(ICurrencyProviderFactory factory)
{
_currencyProvider = factory.Create();
}
In your ServiceCollection or whereever you resolve your dependencies you should include the correct factory.
So for Production, you add the ConfigurationCurrencyProviderFactory, for UnitTest the UnitTestCurrencyProviderFactory. Your actual code then should depend on ICurrencyProviderFactory.
What you actually need to apply along with your factory is the Strategy Pattern
interface ICurrencyProvider {
//...members
}
public interface ICurrencyProviderStrategy {
string Name { get; }
ICurrencyProvider Create();
}
public interface ICurrencyProviderFactory {
ICurrencyProvider GetCurrencyServiceProvider(string providerName);
}
An implementation of the factory would depend on a collection of strategies to call upon to create the desired types.
public class CurrencyProviderFactory : ICurrencyProviderFactory {
private readonly IEnumerable<ICurrencyProviderStrategy> strategies;
public CurrencyProviderFactory(IEnumerable<ICurrencyProviderStrategy> strategies) {
this.strategies = strategies;
}
public ICurrencyProvider GetCurrencyServiceProvider(string providerName) {
var provider = strategies.FirstOrDefault(p => p.Name == providerName);
if (provider != null)
return provider.Create();
return null;
}
}
This would allow greater flexibility as any number of strategies can be injected.
Here is an example of a CurrencyLayerWrapper Strategy
public class CurrencyLayerWrapperProvider : ICurrencyProviderStrategy {
public string Name { get { return "CurrencyLayerAPI"; } }
public ICurrencyProvider Create() {
return new CurrencyLayerWrapper();
}
}
The problem is that the Azure WebJobs SDK supports only public static methods as job entry-points which means there is no way of implementing constructor/property injection.
I am unable to find anything about this topic in official WebJobs SDK documentation/resources. The only solution that I came across is based on service locator (anti) pattern described on this post here.
Is there a good way to use "proper" dependency injection for projects based on Azure WebJobs SDK?
Azure WebJobs SDK now supports instance methods. Combining this with a custom IJobActivator allows you to use DI.
First, create the custom IJobActivator that can resolve a job type using your favourite DI container:
public class MyActivator : IJobActivator
{
private readonly IUnityContainer _container;
public MyActivator(IUnityContainer container)
{
_container = container;
}
public T CreateInstance<T>()
{
return _container.Resolve<T>();
}
}
You need to register this class using a custom JobHostConfiguration:
var config = new JobHostConfiguration
{
JobActivator = new MyActivator(myContainer)
};
var host = new JobHost(config);
Then, you can use a simple class with instance methods for your jobs (here I'm using Unity's constructor injection feature):
public class MyFunctions
{
private readonly ISomeDependency _dependency;
public MyFunctions(ISomeDependency dependency)
{
_dependency = dependency;
}
public Task DoStuffAsync([QueueTrigger("queue")] string message)
{
Console.WriteLine("Injected dependency: {0}", _dependency);
return Task.FromResult(true);
}
}
This is how I handled scoping using the new SDK. Using the IJobactivator as described by Alexander Molenkamp.
public class ScopedMessagingProvider : MessagingProvider
{
private readonly ServiceBusConfiguration _config;
private readonly Container _container;
public ScopedMessagingProvider(ServiceBusConfiguration config, Container container)
: base(config)
{
_config = config;
_container = container;
}
public override MessageProcessor CreateMessageProcessor(string entityPath)
{
return new CustomMessageProcessor(_config.MessageOptions, _container);
}
private class CustomMessageProcessor : MessageProcessor
{
private readonly Container _container;
public CustomMessageProcessor(OnMessageOptions messageOptions, Container container)
: base(messageOptions)
{
_container = container;
}
public override Task<bool> BeginProcessingMessageAsync(BrokeredMessage message, CancellationToken cancellationToken)
{
_container.BeginExecutionContextScope();
return base.BeginProcessingMessageAsync(message, cancellationToken);
}
public override Task CompleteProcessingMessageAsync(BrokeredMessage message, FunctionResult result, CancellationToken cancellationToken)
{
var scope = _container.GetCurrentExecutionContextScope();
if (scope != null)
{
scope.Dispose();
}
return base.CompleteProcessingMessageAsync(message, result, cancellationToken);
}
}
}
You can the use your custom MessagingProvider in your JobHostConfiguration like
var serviceBusConfig = new ServiceBusConfiguration
{
ConnectionString = config.ServiceBusConnectionString
};
serviceBusConfig.MessagingProvider = new ScopedMessagingProvider(serviceBusConfig, container);
jobHostConfig.UseServiceBus(serviceBusConfig);
After asking my own question about how to handle scoping ... I've just came up to this solution: I don't think this is ideal but I couldn't find any other solution for the moment.
In my example I am dealing with ServiceBusTrigger.
As I am using SimpleInjector, the implementation of the IJobActivator interface looks like that:
public class SimpleInjectorJobActivator : IJobActivator
{
private readonly Container _container;
public SimpleInjectorJobActivator(Container container)
{
_container = container;
}
public T CreateInstance<T>()
{
return (T)_container.GetInstance(typeof(T));
}
}
Here, I am dealing with Triggered webjobs.
So I have two dependencies:
A singleton:
public interface ISingletonDependency { }
public class SingletonDependency : ISingletonDependency { }
And another that need to live only the time my function is triggered:
public class ScopedDependency : IScopedDependency, IDisposable
{
public void Dispose()
{
//Dispose what need to be disposed...
}
}
So in order to have a process that run independently from the webjob. I've encapsulated my process into a class :
public interface IBrokeredMessageProcessor
{
Task ProcessAsync(BrokeredMessage incommingMessage, CancellationToken token);
}
public class BrokeredMessageProcessor : IBrokeredMessageProcessor
{
private readonly ISingletonDependency _singletonDependency;
private readonly IScopedDependency _scopedDependency;
public BrokeredMessageProcessor(ISingletonDependency singletonDependency, IScopedDependency scopedDependency)
{
_singletonDependency = singletonDependency;
_scopedDependency = scopedDependency;
}
public async Task ProcessAsync(BrokeredMessage incommingMessage, CancellationToken token)
{
...
}
}
So now when the webjob starts, I need to register my dependencies depending their scopes:
class Program
{
private static void Main()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new ExecutionContextScopeLifestyle();
container.RegisterSingleton<ISingletonDependency, SingletonDependency>();
container.Register<IScopedDependency, ScopedDependency>(Lifestyle.Scoped);
container.Register<IBrokeredMessageProcessor, BrokeredMessageProcessor>(Lifestyle.Scoped);
container.Verify();
var config = new JobHostConfiguration
{
JobActivator = new SimpleInjectorJobActivator(container)
};
var servicebusConfig = new ServiceBusConfiguration
{
ConnectionString = CloudConfigurationManager.GetSetting("MyServiceBusConnectionString")
};
config.UseServiceBus(servicebusConfig);
var host = new JobHost(config);
host.RunAndBlock();
}
}
And this is the triggered job:
Only have one dependency : the IoC container. Because this class is part of my composition root, it should be ok.
It handle the scope into the triggered function.
public class TriggeredJob
{
private readonly Container _container;
public TriggeredJob(Container container)
{
_container = container;
}
public async Task TriggeredFunction([ServiceBusTrigger("queueName")] BrokeredMessage message, CancellationToken token)
{
using (var scope = _container.BeginExecutionContextScope())
{
var processor = _container.GetInstance<IBrokeredMessageProcessor>();
await processor.ProcessAsync(message, token);
}
}
}
I've used a couple patterns that rely on the concept of child containers/scopes (depending on the terminology of your IoC container of choice). Not sure which ones support it, but I can tell you that StructureMap 2.6.x and AutoFac do.
The idea is to spin up a child scope for each message coming in, inject any context that's unique to that request, resolve the top-level object from the child scope, and then run your process.
Here's some generalized code showing it with AutoFac. It does do a direct resolve from the container, similar to the anti-pattern you're attempting to avoid, but it's been isolated to one place.
In this case, it's using a ServiceBusTrigger to fire the job, but could be anything - a job host could potentially have a list of these for the different queues/processes.
public static void ServiceBusRequestHandler([ServiceBusTrigger("queuename")] ServiceBusRequest request)
{
ProcessMessage(request);
}
This method is called by all instances of the above methods. It wraps creation of the child scope in a using block to make sure things are cleaned up. Then, any objects that would vary per request and contain context used by other dependencies (user/client information, etc) would be created and injected into the child container (in this example, the IRequestContext). Finally, the component doing the work would be resolved from the child container.
private static void ProcessMessage<T>(T request) where T : IServiceBusRequest
{
try
{
using (var childScope = _container.BeginLifetimeScope())
{
// create and inject things that hold the "context" of the message - user ids, etc
var builder = new ContainerBuilder();
builder.Register(c => new ServiceRequestContext(request.UserId)).As<IRequestContext>().InstancePerLifetimeScope();
builder.Update(childScope.ComponentRegistry);
// resolve the component doing the work from the child container explicitly, so all of its dependencies follow
var thing = childScope.Resolve<ThingThatDoesStuff>();
thing.Do(request);
}
}
catch (Exception ex)
{
}
}
All answers to the question are outdated now. Using the latest packages you can easily get constructor injection right out of the box. Two steps are only required:
Create the event handler function as an instance method in a non-static class. Let's call the class QueueFunctions.
Add your class to the list of services.
builder.ConfigureServices(services =>
{
// Add
// dependencies
// here
services.AddScoped<QueueFunctions>();
});
Now, you'll be able to inject dependencies through the constructor.
I know Unity can be configured to use a class' constructor to create an instance of a class (like below) but that's not what I want.
container.RegisterType<IAuthoringRepository, AuthoringRepository>();
I would like to configure Unity to use a factory method with the windows identity passed as a parameter (ie: RepositoryFactory.CreateAuthoringRepository(WindowsIdentity.GetCurrent())) when resolving a type of IAuthoringRepository. How do i do this?
One way is to have RepositoryFactory implement IRepositoryFactory, then register that. Resolved types can get a factory, then call its CreateAuthoringRepository method. You could create an overload called CreateAuthoringRepositoryForCurrentIdentity if desired, or register an IIdentity dependency of the factory with Unity.
I'd probably just inject a factory and leave the CreateAuthoringRepository method as you have it, then have the clients pass WindowsIdentity.GetCurrent(). That way the identity is always fresh, and you can mock the factory for testing.
Alternately, you can specify a delegate with InjectionFactory:
void Main()
{
using (var container = new UnityContainer())
{
container.RegisterType<IAuthoringRepository>(
new InjectionFactory(c => CreateAuthoringRepository()));
Console.WriteLine("debug - resolving model");
var model = container.Resolve<Model>();
}
}
public IAuthoringRepository CreateAuthoringRepository()
{
Console.WriteLine("debug - calling factory");
return new AuthoringRepository
{ Identity = WindowsIdentity.GetCurrent() };
}
public class Model
{
public Model(IAuthoringRepository repository)
{
Console.WriteLine(
"Constructing model with repository identity of "
+ repository.Identity);
}
}
public interface IAuthoringRepository
{
IIdentity Identity { get; }
}
public class AuthoringRepository : IAuthoringRepository
{
public IIdentity Identity { get; set; }
}
This prints:
debug - resolving model
debug - calling factory
Constructing model with repository identity of System.Security.Principal.WindowsIdentity
That's for Unity 2.0. With earlier versions, see StaticFactoryExtension.
Now method InjectionFactory is obsolete. That's why it'd be better to use method RegisterFactory. Below I am showing how the previous code changed. How you see I changed the method CreateAuthoringRepository. Now it is the static method with one param IUnityContainer container
void Main()
{
using (var container = new UnityContainer())
{
container.RegisterFactory<IAuthoringRepository>(CreateAuthoringRepository);
Console.WriteLine("debug - resolving model");
var model = container.Resolve<Model>();
}
}
public static IAuthoringRepository CreateAuthoringRepository(IUnityContainer container)
{
Console.WriteLine("debug - calling factory");
return new AuthoringRepository
{ Identity = WindowsIdentity.GetCurrent() };
}
public class Model
{
public Model(IAuthoringRepository repository)
{
Console.WriteLine(
"Constructing model with repository identity of "
+ repository.Identity);
}
}
public interface IAuthoringRepository
{
IIdentity Identity { get; }
}
public class AuthoringRepository : IAuthoringRepository
{
public IIdentity Identity { get; set; }
}
Can anyone help?
I have a wpf app (shouldn't matter) and in the Onstart i have my bootstrap stuff.. Its like this..
// Create unity container my service and repository
container = new UnityContainer()
.RegisterType<ISecurityRepository, SecurityRepository>()
.RegisterType<ISecurityService, SecurityService>();
Basically ISecurityService expects me to pass in a ISecurityRepository, hence the above fails.
But i am little confused, do i have to create a new IsecurityRespository and then pass it in, this defeats the object doesn't it?
Is there anyway i say "pass into SecurityService the ISecurityRepository from the container", but it hasn't been built yet?
Any ideas?
You don't have to create instances first. It all just works. That's the magic of IoC Containers.
Example:
public interface ISecurityService { }
public interface ISecurityRepository { }
public class SecurityService : ISecurityService
{
public SecurityService(ISecurityRepository repository)
{
Console.WriteLine("SecurityService created");
Console.WriteLine("Repository is " + repository);
}
public override string ToString()
{
return "A SecurityService";
}
}
public class SecurityRepository : ISecurityRepository
{
public SecurityRepository()
{
Console.WriteLine("SecurityRepository created");
}
public override string ToString()
{
return "A SecurityRepository";
}
}
public class MyClassThatNeedsSecurity
{
public MyClassThatNeedsSecurity(ISecurityService security)
{
Console.WriteLine("My class has security: " + security);
}
}
class Program
{
static void Main()
{
using (IUnityContainer container = new UnityContainer())
{
container.RegisterType<ISecurityRepository, SecurityRepository>()
.RegisterType<ISecurityService, SecurityService>();
MyClassThatNeedsSecurity myClass =
container.Resolve<MyClassThatNeedsSecurity>();
}
}
}
This will print:
SecurityRepository created
SecurityService created
Repository is A SecurityRepository
My class has security: A SecurityService
You have a number of options, such as pre-creating your instances (as you showed in your follow-up post) or extending the lifetime of injected dependencies so that they're not recreated every time they're needed. But for the base case, this will work.
here is some more information. The constructor of my class is
public SecurityService(ISecurityRepository repository)
: base(repository)
{
}
After playing around a little bit, i managed to do the following but this causes me to create instances FIRST ... It seems to work.., but its an alternative.
// Create unity container my service and repository
ISecurityRepository securityRepository = new SecurityRepository();
ISecurityService securityService = new SecurityService(securityRepository);
container = new UnityContainer();
container.RegisterInstance<ISecurityRepository>(securityRepository);
container.RegisterInstance<ISecurityService>(securityService);