.net 7 dependency injection, Mulltiple implementation of same interface - c#

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

Related

Decorating 1 of multiple implemented interfaces

I'm wondering if it's possible to have a decorator for 1 of multiple implemented interfaces in C#. I'm leaning towards no, but maybe.
Here's what I mean
public abstract class Auditable
{
public string CreatedBy { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime ModifiedAt { get; set; }
public string ModifiedBy { get; set; }
}
public class MyClass : Auditable
{
// <...> properties
}
public interface IWriteRepository<T> : where T : Auditable
{
T Create(T entity);
T Update(T entity);
}
public class AuditRepositoryDecorator<T> : IWriteRepository<T> where T : Auditable
{
private readonly IWriteRepository<T> _decorated;
// <...> ctor with injects
public T Create(T entity)
{
entity.ModifiedAt = time;
entity.CreatedAt = time;
entity.CreatedBy = invoker;
entity.ModifiedBy = invoker;
return _decorated.Create(entity);
}
public T Update(T entity)
{
entity.ModifiedAt = time;
entity.ModifiedBy = invoker;
return _decorated.Update(entity);
}
}
public interface IMyClassRepository : IWriteRepository<MyClass>
{
MyClass Get(int id);
}
So I would like to be able to depend on IMyClassRepository repository and whenever Create or Update would get invoked it would go through AuditRepositoryDecorator. It's a piece of logic that is executed a lot and I think it would be much simpler to have as a decorator instead of having a composition relation to some interface that does the same.
IAuditableRepository is never instantiated directly, as it's would always be implemented by another interface, so I think it might not be possible to do what I want to achieve.
I'm using the default dnc2.1 DI framework with Scrutor for decorations.
What you are trying to achieve is not possible. This isn't a limitation of the used DI Container, but rather a constraint of the .NET Type system. I often advise developers that are in DI trouble to, for the sake of understanding, remove the DI Container from the equation and instead build object graphs by hand. This works well in your situation, as I'll demonstrate below.
Assume you have an IMyClassRepository consumer:
public class RepoConsumer
{
RepoConsumer(IMyClassRepository repo) ...
}
And an IMyClassRepository implementation:
public class MyClassRepositoryImpl : IMyClassRepository
{
...
}
Now let's create the object graph for RepoConsumer that uses AuditRepositoryDecorator<MyClass>:
var repo = new MyClassRepositoryImpl();
var decoratedRepo = new AuditRepositoryDecorator<MyClass>(repo);
var consumer = new RepoConsumer(decoratedRepo); // <-- COMPILE ERROR
When you compile this code, you'll notice that the C# compiler will generate an error on the new RepoConsumer line. This is because RepoConsumer expects an IMyClassRepository. Although MyClassRepositoryImpl implements IMyClassRepository, AuditRepositoryDecorator<MyClass> does not implement IMyClassRepository.
To solve this, you might try letting AuditRepositoryDecorator<T> implement IMyClassRepository, but that will obviously be ugly, because the decorator will have to implement a dozen of interfaces, for each entity in your system.
But what this exercise proves, is that the problem is not so much with the DI Container, but rather that the type system simply not permits you to build an object graph of this. And since the type system doesn't allow you to, the DI Container certainly won't allow it. It can't work around the type checks of the type system. Fortunately.
But the solution to your problem is actually really straightforward: remove the specific IMyClassRepository and let consumers depend on IWriteRepository<MyClass> instead. This might seem a disappointing solution, but there is a myriad of problems surrounding deriving from generic interfaces. Just accept the fact that consumers depend on such generic abstraction. It takes some time, but eventually, you will start to love and appreciate this style of programming.
But, of course, this still leaves us with the question of how to add new methods, such as MyClass Get(string). There are multiple solutions, such as:
Implement it as extension method (only possible when the method itself requires access to the interface itself, not to the class's internals)
Define a separate interface, which might be a good idea in general, according to the Interface Segregation Principle
the most used approach in these cases is the repository pattern as explained here in my answer: How do I avoid code repetition when defining a class of functions that only vary the data type of the parameters they handle?
in your case this is the classes hierarchy:
public interface IWriteRepository<T> : where T : Auditable
{
T Create(T entity);
T Update(T entity);
}
public abstract class WriteRepositoryBase<T> : IWriteRepository<T> where T : Auditable
{
//implement create and update
}
public interface IMyRepository : IWriteRepository<MyClass>
{
MyClass Get(string id);
}
public class MyRepository : WriteRepositoryBase<MyClass>, IMyRepository
{
//implement Get
}

Different property value for contracts

I have two interfaces implemented by one main class. How can i refactor my code in a way that on implementing each contract, the methods of each contract has a different value for a parameter such as DatabaseName.
Example :
Class1 Implements Interface1,Interface2
Interface1.GetData() has DatabaseName set to Database 1
Interface2.GetData() has DatabaseName set to Database 2
I can configure those value in the methods GetData() but i want a cleaner way of doing it.
Any pattern recommendation be that DI ,Domain driven ,even basic inheritance example which accomplishes the above is what i am looking for.
It sounds like all you need is explicit interface implementation:
public class Class1 : Interface1, Interface2
{
// Note the lack of access modifier here. That's important!
Data Interface1.GetData()
{
// Implementation for Interface1
}
Data Interface2.GetData()
{
// Implementation for Interface2
}
}
Obviously the two methods can call a common method with a parameter to specify the database name or similar.
Refactoring is usually motivated by noticing a code smell and the very fact that you ended up in a situation where you have to implement 2 abstraction which expose similar functionality is the code smell.
Without having more understanding of the problem I might not be able to provide you a conclusive answer but with limited understanding this is what I would propose. Have 2 different concrete implementation each implementing one interface and have a factory which would be injected to client and make the client make the deliberate decision which one of these implementation is needed. In case these concrete classes share common functionality you can always abstract that into a common parent class.
public interface ISQLReader
{
string GetData();
}
public interface IOracleReader
{
string GetData();
}
public abstract class Reader
{
protected void CommonFunctionaility()
{
}
}
public class MSSQLReader : Reader, ISQLReader
{
public string GetData()
{
return "MSSQL";
}
}
public class OracleReader : Reader, IOracleReader
{
public string GetData()
{
return "Oracle";
}
}
public interface IReaderFactory
{
OracleReader CreateOracleReader();
MSSQLReader CreateMSSQLReader();
}
public class ReaderFactory : IReaderFactory
{
public MSSQLReader CreateMSSQLReader() => new MSSQLReader();
public OracleReader CreateOracleReader() => new OracleReader();
}
public class ReaderClient
{
private IReaderFactory _factory;
public ReaderClient(IReaderFactory factory)
{
this._factory = factory;
}
}
Explicit interface implementation is technique that should restrict usage of the functionality until the client has made and explicit cast there by making a deliberate decision.

Register decorators based on consumers via simple injector

Lets say that I have two services that depend on one interface:
class Service1
{
...
Service1(IDependency dependency) { ... }
...
}
and
class Service2
{
...
Service2(IDependency dependency) { ... }
...
}
IDependency is registered by some concrete implementation. How can I register decorator to IDependency implementation that can be consumed only by Service2? In other words IDependency should be resolved to an instance of the decorator only inside Service2. Is it possible?
You can use context-based injection
// Register decorators first
container.RegisterConditional<IDependency, DependencyDecorator1>(
c => c.Consumer.ImplementationType == typeof(Service1));
container.RegisterConditional<IDependency, DependencyDecorator2>(
c => c.Consumer.ImplementationType == typeof(Service2));
// Register the real implementation last using !c.Handled
container.RegisterConditional<IDependency, RealImplementationDependency>(
c => !c.Handled);
See the note from the documentation:
Note: In many cases context based injection is not the best solution,
and the design should be reevaluated. In some narrow cases however it
can make sense.
Alternatively, you could derive separate interfaces that extend IDependency and use those, one for each service. This might be more appropriate to differentiate the dependencies. In this case, you'd simply register different implementation/instances for each interface.
For example, you might have a file storage abstraction against a cloud storage service. The basic interface encapsulates all the file storage actions, then you extend it for specific buckets within the storage container. You can provide a single implementation (via delegate registration) that takes the storage bucket as a constructor parameter for each named interface. The use of named interfaces that identify the bucket purpose enhance code comprehension.
public interface IFileStorage
{
...
}
public interface IUploadStorage : IFileStorage { /* empty interface */ }
public interface IContentStorage : IFileStorage { /* empty interface */ }
public class FileStorage : IUploadStorage, IContentStorage
{
public FileStorage(string containerName) { ... }
...
}
public UploadService(IUploadStorage storage)
{
...
}
public ContentService(IContentStorage storage)
{
...
}
container.Register<IUploadStorage>(() = new FileStorage(Containers.Upload));
container.Register<IContentStorage>(() = new FileStorage(Containers.Content));

Simple Injector register multiple type of same interface with metadata

I have the following problem. I have one interface say IFoo and multiple implementations from it. Now, I have one web API controller, which according to some circumstances, should create a particular type of IFoo descendant, call it's method(s) and return result. The logic of the controller doesn't change no matter which implementation of IFoo I use. For this task, I need to tell the container which IFoo implementation to create from the controller, the problem is that, I don't know how to do that (if it's even possible with Simple Injector).
P.S. I already thought about RegisterAll, but in this case I'm forced to create all IFoo descendants (and pass it to the controller) when I need only one. This is not a solution for me.
Another solution would be to create different controllers for different IFoo implementations and use context based injection, but this will result in duplicated code/controllers that I want to avoid.
Ideally, the solution should be something like
container.RegisterAllWithMetadata(IEnumerable<Type> types, IEnumerable<string> metadata)
container.GetInstance(Type type, string metadata)
Is it possible to achieve my goal with Simple Injector?
sorry for bringing it back to life, but as it was said in the comments by Steven, your answer is in the docs
In situations where a service needs to create multiple instances of a certain dependencies, or needs to explicitly control the lifetime of such dependency, abstract factories can be used. Instead of injecting an IMyService, you should inject an IMyServiceFactory that creates new instances of IMyService:
// Definition
public interface IMyServiceFactory {
IMyService CreateNew();
}
// Implementation
sealed class ServiceFactory : IMyServiceFactory {
public IMyService CreateNew() {
return new MyServiceImpl();
}
}
// Registration
container.RegisterSingle<IMyServiceFactory, ServiceFactory>();
// Usage
public class MyService {
private readonly IMyServiceFactory factory;
public MyService(IMyServiceFactory factory) {
this.factory = factory;
}
public void SomeOperation() {
using (var service1 = this.factory.CreateNew()) {
// use service 1
}
using (var service2 = this.factory.CreateNew()) {
// use service 2
}
}
}

About DI and SRP

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.

Categories