I have a series of classes each with several dependencies according to their role. These dependencies are being injected into the constructor. An example would be:
public class UserViewModel
{
//...
public UserViewModel(IDataService dataService,
INotificationService notificationService,
IDialogService dialogService,
INavigationService navigationService)
{
this.DataService = dataService;
this.NotificationService = notificationService;
this.DialogService = dialogService;
this.NavigationService = navigationService;
}
}
As you can see, there are several arguments to set. I could write an interface like the following:
public interface IInteractionService
{
public INotificationService NotificationService { get; set; }
public IDialogService DialogService { get; set; }
public INavigationService { get; set; }
}
and pass the injected InteractionService implementation to the UserViewModel's constructor in one piece:
public UserViewModel(IDataService dataService,
IInteractionService interactionService) {}
and use it like:
this.InteractionService.NotificationService.Publish(message);
Are there any issues with using an interaction interface holding interface properties in terms of design patterns/principles? Or is there a better way to look at it?
Thanks for any advice...
In general, you should not create "God" service with different services inside. It breaks Single Response Principle (SRP).
But I do not understand how it can be that DI injects you null against instance of service? May be you should fix this behaviour against creating "God" service?
IMO, dependency injection in a constructor is a way to hell. Could you predict the final number of dependencies during the lifetime of your application? Do you really want to modify ctor's code everytime? Do you really want to initialize all dependencies at once, instead of lazy initialization?
MEF, e.g., can inject private fields in lazy manner.
You definitely shouldn't test for null injected values. If your DI-framework doesn't make these tests itself, then throw it away and use normal one.
Related
In my startup.cs I have code like this
services.AddScoped<IFileStorage, DiskFileStorage>();
service.Add<IImageHandler, ImageHandler>();
public class ImageHandler
{
ImageHandler(IFileStorage fileStorage, ...){}
}
now I want to add another class, OtherHandler, that takes a IFileStorage interface, but with another implementation, something like this
services.AddScoped<IFileStorage, NetworkFileStorage>();
public class OtherHandler:IOtherHandler
{
OtherHandler(IFileStorage, fileStorage)
}
Now how do i configure stuff so that the OtherHandler would use the NetworkFileStorage implementation for IFileStorage and anything else would use a default DiskFileStorage implementation?
Update:
Thanks to gunr2171 comment, I discovered that I could do a
services.AddScoped<IOtherHandler>(provider => new OtherHandler(provider.GetRequiredService<NetworkFileStorage>())); to get a specific implementation. But still curious if it is possible if I for some reason wanted to use an interface.
So, based on my understanding this is your scenario:
public interface IFileStorage
{
}
public class NetworkFileStorage: IFileStorage
{
}
public class DiskFileStorage: IFileStorage
{
}
You also have a couple of services depending on the IFileStorage service:
public class ImageHandler: IImageHandler
{
public ImageHandler(IFileStorage fileStorage)
{
}
}
public class OtherHandler: IOtherHandler
{
public OtherHandler(IFileStorage fileStorage)
{
}
}
You want to register your services so that both of the followings hold true:
instances of ImageHandler are built by injecting NetworkFileStorage
instances of OtherHandler are built by injecting DiskFileStorage
For simplicity, I'll suppose that all the involved types are implemented so that it is ok to register them as singletons. This depends on the actual implementation, in any case the pattern that I'm going to show you doesn't depend on the actual lifetime of the involved types.
First of all, register the concrete implementations of the IFileStorage interface. You need to register the classes (not the interface): the purpose of this is making sure that the DI container knows these types and it is able to provide you instances of both types.
services.AddSingleton<NetworkFileStorage>();
services.AddSingleton<DiskFileStorage>();
Now, you can register an implementation for the IImageHandler service.
You will use the ImageHandler class as the implementing type and you will also provide a factory method to the DI container: by doing so, you are able to select the implementation of IFileStorage to be injected (in this case you will select the NetworkFileStorage type).
services.AddSingleton<IImageHandler>(sp =>
{
var fileStorage = sp.GetRequiredService<NetworkFileStorage>();
return ActivatorUtilities.CreateInstance<ImageHandler>(sp, fileStorage);
});
You can do a similar thing to register the OtherHandler class as the implementation for the IOtherHandler service, and select the class DiskFileStorage as the type being injected in the constructor of OtherHandler:
services.AddSingleton<IOtherHandler>(sp =>
{
var fileStorage = sp.GetRequiredService<DiskFileStorage>();
return ActivatorUtilities.CreateInstance<OtherHandler>(sp, fileStorage);
});
Let me add a final note on your design. There is something wrong with it.
It seems to me that the ImageHandler class is somewhat strongly coupled with the NetworkFileStorage class, while the OtherHandler class is somewhat strongly coupled with the DiskFileStorage class.
I would expect both of these classes to work fine with any implementation of the IFileStorage interface. If these classes do really depend only on the behavior described by the IFileStorage interface, then any actual implementation of that behavior should be fine for them to work as expected. This is basically a violation of the Liskov Substitution Principle.
If this is not the case, maybe the interface IFileStorage is not a useful abstraction for your domain model and you should considered to redesign it or to define two different interfaces (one suited to the needs of the ImageHandler class and the other suited to the needs of the OtherHandler class).
I think there might be a more flexible approach here. It uses Adapter pattern for your services, allowing you to stay away from registering concrete implementations, and doesn't force you to instantiate every type manually that uses some FileStorage implementation.
// A generic storage that can be used for any scenario
public interface IFileStorage<T> where T : IFileAdapter
{
protected T Adapter { get; }
Task Handle();
}
// a base interface that defines the shape of adapter
public interface IFileAdapter
{
Task Handle();
}
// copy interfaces to separate the services
public interface ILocalFileAdapter : IFileAdapter
{
}
public interface IRemoteFileAdapter : IFileAdapter
{
}
// specific implementations
public class RemoteFileAdapter : IRemoteFileAdapter
{
private readonly ILogger<RemoteFileAdapter> logger;
public RemoteFileAdapter(ILogger<RemoteFileAdapter> logger)
{
this.logger = logger;
}
public Task Handle()
{
this.logger.LogWarning("Handling file remotely");
return Task.CompletedTask;
}
}
public class LocalFileAdapter : ILocalFileAdapter
{
private readonly ILogger<LocalFileAdapter> logger;
public LocalFileAdapter(ILogger<LocalFileAdapter> logger)
{
this.logger = logger;
}
public Task Handle()
{
this.logger.LogWarning("Handling file locally");
return Task.CompletedTask;
}
}
// generic storage that uses an adapter to handle the scenario
public class FileStorage<T> : IFileStorage<T> where T : IFileAdapter
{
public FileStorage(T fileAdapter)
{
Adapter = fileAdapter;
}
public T Adapter { get; }
public Task Handle()
{
return this.Adapter.Handle();
}
}
Register your services like below :
builder.Services.AddSingleton<ILocalFileAdapter, LocalFileAdapter>();
builder.Services.AddSingleton<IRemoteFileAdapter, RemoteFileAdapter>();
// aspnet.core allows you to register generic services
builder.Services.AddSingleton(typeof(IFileStorage<>), typeof(FileStorage<>));
And this is how you use your IFileStorageService:
public WeatherForecastController(IFileStorage<ILocalFileAdapter> localFileStorage, IFileStorage<IRemoteFileAdapter> remoteFileStorage)
{
localFileStorage.Handle();
remoteFileStorage.Handle();
}
// which will log :
// Handling file locally
// Handling file remotely
I have lack of understanding in this basic concept of OOP. Here is an example:
Say I have a base repository which is derived by 3 different classes. The base class requires the dbContext in the constructor , injected by dependency injection. Because of this the child classes have to pass the dbContext every time I instantiate them. The requirement is simple: The base class should instantiate the Context for the child classes. Is that possible? I do not want the child classes to worry about the context. I just want them to call it.
Here is my base class.
public class CastingBaseRepository<TEntity> : ICastingBaseRepository<TEntity> where TEntity : class, IEntity
{
private readonly CastingContext _context;
public CastingBaseRepository(CastingContext context) => _context = context ?? throw new ArgumentNullException(nameof(context));
// Context property
public CastingContext Context => _context;
}
Heres how the child class would be:
public class CommercialJobsRepository : CastingBaseRepository<Audition>, ICommercialJobsRepository
{
/* I do not want to use base(context) here. I need a way for this class to just call Context property from the derived class.. Possible? */
private CastingContext _context;
public CommercialJobsRepository(CastingContext context) : base(context)
{
_context = context;
}
public async Task<IList<OpenJobs>> GetOpenJobs()
{
// test code
var tt = await _context.Audition.Take(10).ToListAsync();
return new List<OpenJobs>();
}
}
Here is my context class
public partial class CastingContext : DbContext
{
public virtual DbSet<Audition> Audition { get; set; }
public CastingContext(DbContextOptions<CastingContext> options) : base(options)
{
}
}
And here is the startup.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// DB Context
services.AddDbContextPool<CastingContext>(options => { options.EnableSensitiveDataLogging(); options.UseSqlServer(Configuration.GetConnectionString("dbCast")); });
}
}
I am using strategy pattern to determine which child class would be accessed at runtime. That too needs to have CastingContext injected the constructor which is again ugly. The point is, there should be only one class exposing the context to all derived classes or perhaps through a static method. Can you please help me understand how to do it?
Here is my Strategy class:
public class JobsStrategyContext
{
private readonly CastingContext _context;
private readonly Dictionary<eBreakdownTypes, IJobsRepository> Strategies =
new Dictionary<eBreakdownTypes, IJobsRepository>();
public JobsStrategyContext(CastingContext context)
{
_context = context;
Strategies.Add(eBreakdownTypes.Ftv, new FtvJobsRepository(_context));
Strategies.Add(eBreakdownTypes.Commercial, new CommercialJobsRepository(_context));
Strategies.Add(eBreakdownTypes.Theatre, new TheatreJobsRepository(_context));
}
public async Task<IList<OpenJobs>> GetOpenJobsBySubType(eBreakdownTypes breakdownType)
{
return await Strategies[breakdownType].GetOpenJobs();
}
}
No, you cannot both at the same time use dependency injection and hardcode the instantiation of your dependency in the base class. If you want to inject the dependency from an external consumer, it needs to pass through the derived constructor.
At best, you can pass a service locator which the base constructor then uses to fetch the dbcontext, but then you're still handling the service locator in the derived class. But service locators are no longer considered good practice because they have notable drawbacks such as decreasing readability/usability and becoming a general nuisance to handle in sufficiently large codebases.
While it would technically achieve what you want to achieve, don't start using static service locators. The costs far outweigh the benefits.
However, the problem outset doesn't quite make sense to me. If you're using dependency injection, I would assume you're using some sort of automated injection where you don't have to manually instantiate all dependencies.
Yes, you still need to mention the dbcontext as a (derived and base) constructor parameter, but your derived classes don't need to handle it (other than passing it to the base constructor. The effort to do so is minimal and it allows for maximum freedom in terms of dependency injection.
This is how inheritance works by design.
This is a functional limitation of C# as a language. You don't have to provide the same constructor(s) in child classes as you have in the base class, but you must satisfy those constructors in the base class. For example:
public class BaseClass
{
public BaseClass(Dependency dep) {}
}
public class ChildClass
{
public ChildClass(Dependency dep) : base(dep) {}
}
Or:
public class ChildClass
{
public ChildClass() : base(new Dependency()) {}
}
In either case, you somehow, someway must provide the Dependency instance to the base class constructor, but you may opt to not actually construct the child class with that dependency, and instead, get it internally.
However, in practical terms with something like DbContext which relies itself on dependencies being injected, it's going to require carrying that dependency all the way through: your child class will need a constructor where it can be injected in order to then pass down into the base class constructor.
You have to provide the dependency through the child class because, When you are creating an instance of the child class, the base class is also getting constructed and hence the dependencies must be supplied.
Of course for the ease of coding and managing these dependencies,you can use Use the IoC containers like Unity to handle the automatic dependency injections (The Unity Application dependency injection container with support for constructor, property, and method call injection)
I'm writing the following class
public class UserApplication
{
private IUserRepository UserRepository { get; set; }
private IUserEmailerService UserEmailerService { get; set; }
public UserApplication(IUserRepository userRepository, IUserEmailerService userEmailerService)
{
this.UserRepository = userRepository;
this.UserEmailerService = userEmailerService;
}
public bool Authenticate(string login, string pass)
{
// Here I use UserRepository Dependency
}
public bool ResetPassword(string login, string email)
{
// Here I only use both Dependecies
}
public string GetRemeberText(string login, string email)
{
// Here I only use UserRepository Dependency
}
}
I'm using Unity for manage my instances so I realised that I only use both dependencies on only one method so when I ask the container to give a instance for this class both dependencies are inject into this class but I don't need the two instances for all methods so in Authenticate user I only need the repository.
So am I wrong doing this? Is there another way that only have the dependecy I use for all cases in this class?
I think of using the Command Pattern to that so I class 3 classes with one method and only the dependencies I need inside that like this:
public class AuthenticateUserCommand : ICommand
{
private IUserRepository UserRepository { get; set; }
public string Login { get; set; }
public string Password { get; set; }
public void Execute()
{
// executes the steps to do that
}
}
public class ResetUserPasswordCommand : ICommand
{
private IUserRepository UserRepository { get; set; }
private IUserEmailerService UserEmailerService { get; set; }
public string Login { get; set; }
public string Email { get; set; }
public void Execute()
{
// executes the steps to do that
}
}
Another approach is to create a role-specific interface for each behavior. So you'd have IUserAuthenticationService, IUserPasswordResetService, and IUserRememberPasswordService. The interfaces could be implemented by a single class, such as UserApplication or they could be implemented with individual classes to maintain SRP. The command pattern you describe has a similar advantage for SRP. One issue with the command pattern is that those dependencies still have to be provided by something. If the dependencies are provided by the controller, then you still have to get the dependencies to the controller in the first place and you are left with a similar problem as your first example.
The trade-off in the role-specific interface case as well as the command pattern is a loss of cohesion. The cost of this is certainly a matter of preference and perspective as is the degree to which you want to enforce SRP. On one hand, the cohesion provided by having a single class handle authentication related behavior can be beneficial. On the other hand, it can lead to a dependency misalignment as you describe.
I usually implement a form of the command pattern as you are considering doing. However, it also has elements of what eulerfx has mentioned. I just call them tasks. For example:
public interface ITask
{
void Execute();
}
public interface IAuthenticateTask : ITask {}
public interface IResetPasswordTask : ITask {}
I then implement these and have the required dependencies injected. So I have role specific interfaces and implementations.
I would not go with the service locator as you stated in your answer bit.
When I do have a situation where I need access to various tasks as I do in the controller of an ASP.NET MVC project I use property injection instead of constructor injection. I just have my DI container (I use castle) require certain injections based on a convention at runtime.
In this way I can still easily test the controller since I do not need to provide all the constructor injected objects but only those properties that I need for the test, with the added benefit that certain injected properties will still be required just as would be provided by constructor injection.
update:
There are a couple of options available using this approach. The main interface one would be interested in for a task is the role-specific one. The inherited interface(s) such as ITask would be only for convenience in simple cases. It can be extended also with generics:
public interface ITask<TInput>
{
void Execute(TInput input);
}
public interface IOutputTask<TOutput>
{
TOutput Execute();
}
public interface IOutputTask<TOutput, TInput>
{
TOutput Execute(TInput input);
}
Once again these are for convenience:
public interface IAuthenticateTask : IOutputTask<bool> {}
// or
public interface IAuthenticateTask : IOutputTask<AuthenticationResult> {}
You could work just on the role level:
public interface IAuthenticateTask
{
AuthenticationResult Execute(string username, string password);
}
One need only rely on the role-specific interface for dependencies.
So am I wrong doing this?
No. 2 dependencies are not the end of the world, they don't make the constructor bloated or unreadable.
Previously given answers would be good fits for cases when you have 3-4+ dependencies though.
You could also occasionally pass a particular dependency as a parameter to a method if it is only used in that method. In this sense, you might want to give Unity's method call injection a try although I'm not sure it was precisely intended for that purpose.
I am trying to use property injection for StructureMap in a plug-in style system.
ObjectFactory.Initialize(o => o.Scan(s =>
{
s.AssembliesFromPath("path_to_assemblies");
s.WithDefaultConventions();
});
Here is a sample implementation (purposely did not go deeper in defining T and TU as they are just simple classes)
public interface IBarService
{
void Baz();
}
public class BarService : IBarService
{
public void Baz() { /* implementation */ }
}
public abstract class PluginBase<T, TU> : IPlugin
where T : AClass, new()
where TU : BClass
{
protected PluginBase()
{
//some init code in the constructor
}
}
//Foo is created at run-time via Activator.CreateInstance()
public class FooPlugin : PluginBase<AClass, BClass>
{
[SetterProperty]
public IBarService BarService { get; set; }
public void Fooey()
{
BarService.Baz();
}
}
I want to auto-wire the property dependencies on all of these plug-ins that are created at run-time. I thought I'd start out with property injection and then move things to the constructor if the need arose.
If I do:
var obj = ObjectFactory.GetInstance<IBarService>();
anywhere in an instance of FooPlugin, I get the correct implementation and all is well.
If I do:
this.BarService.Baz();
I get a null reference exception because no instance of IBarService was set.
After I create my plug-in, if I do this:
ObjectFactory.BuildUp(pluginObject).
All is well and FooPlugin has the correct implementation of IBarService.
Is there any way to simply allow me to decorate my plugin properties with [SetterProperty] and have StructureMap automatically inject those when the Plugin is created without having to call ObjectFactory.BuildUp(pluginObject) ?
How are you creating your plugin instance in the cases where it doesn't work? Are you just doing new FooPlugin()?
If you do var plugin = ObjectFactory.GetInstance<PluginBase<AClass, BClass>>();, do you get the plugin with all the correct dependencies resolved?
If you are instantiating the object with "new", the container has no way to know that the instance needs dependencies resolved--it has no knowledge of that instance. Instances that need injected dependencies must be "managed by the container" so to speak.
You'll save yourself a lot of trouble if you just go the opposite route and inject all dependencies in the contstructor(s). This way there is a single place where you need to check if your objects are initialized properly...
I'm currently trying to work out how to set the initial values for some fields using Ninject.
I have something like this:
public class SomeClass
{
private ISomething _something;
public SomeClass(string someParam)
{
}
public void DoAThing()
{
_something.DoSomething();
}
}
My dilemma comes about in the setting of _something to an initial value, given I don't want the class to know anything about which default implementation of ISomething to use, is there a way of achieving this in Ninject?
I should add that passing the initial values in via the constructor is not an option.
I should also add that this is in a class-library, so any information on how and when the setup of the kernel & injection should take place would be great :)
Elaboration: It seems that people could be getting confused, I am not trying to get an ISomething into the class (it isn't a dependency), rather, the default implementation of ISomething is the dependency, this is why I went for the service-locator pattern, for actual dependencies I would of course have them in the constructor.
Thanks.
Yes, it's not very good to have highly coupled classes, thus depending on abstractions is a good choice. But hiding your dependencies is not very good solution. Make them visible to clients of your class, and use dependency injection to provide concrete implementations of dependencies to your class:
public class SomeClass
{
private ISomething _something;
public SomeClass(ISomething something, string someParam)
{
_something = something;
}
public void DoAThing()
{
_something.DoSomething();
}
}
Also consider to create factory, which will provide default implementation of ISomething to created SomeClass objects.
In the end I decided to go with a static IOC access class to allow my code to gain access to the core Ninject Kernel used by the class library for the main injection.
So:
internal static class IOC
{
private static readonly IKernel _kernel;
static IOC()
{
_kernel = new StandardKernel(new IModule[] {
new SomethingModule(),
});
}
static T Get<T>()
{
return _kernel.Get<T>();
}
}
internal sealed class SomethingModule : StandardModule
{
public override void Load()
{
Bind<ISomething>().To<ConcreteSomething>(
new ConstructorParam("arg", "value"));
}
}
Then in my previous class:
public class SomeClass
{
private ISomething _something;
public SomeClass(string someParam)
{
_something = IOC.Get<ISomething>();
}
public void DoAThing()
{
_something.DoSomething();
}
}
Now I can get concrete implementations and even have them initialised with default values to boot!
The way of getting the concrete classes initialised with default values is a little flimsy, but I'm sure there are smarter ways of achieving this in Ninject, but it does appear that a hybrid solution of service-locator-esque code and Ninject works quite well!
BTW I believe you could also have multiple IOC containers in differing scopes (themselves passed along via Ninject :P) to prevent creating a behemoth "everything everywhere" kernel.
Hope this helped someone!