Can we call a parameterized constructor from a parameterless constructor? - c#

For example I have class like this
public class ABC
{
private readonly IMemoryCache _cache;
private readonly IConfiguration _config;
private readonly IDistributedCache _distributedCache;
public ABC(IMemoryCache memoryCache, IConfiguration config, IDistributedCache distributedCache)
{
_cache = memoryCache;
_config = config;
_distributedCache = distributedCache;
}
public ABC() : this(IMemoryCache , IConfiguration ,IDistributedCache )
{
}
}
As you can see that I have tried to call a Parameterized constructor from a Parameter-less constructor, but that's not possible. Is there any other way to achieve this concept?

You need to pass in concrete implementations of those interfaces, It's just like calling a method. There is nothing magical about this() syntax apart from where it appears. For example if you have a default implementation of IMemoryCache implemented in class DefaultMemoryCache you can just 'new that up' and pass it in:
public ABC() : this(new DefaultMemoryCache(), etc.)
{
}
Alternatively, you can use a static factory method if constructing these dependencies is a bit too complicated:
public static ABC CreateNew()
{
var others = ...
var cache = new DefaultCache(others, etc.)
...
return new ABC(cache, etc.);
}
But if you want to be able to use the interface as your input, this is what you can do: (Now, this is just an example to make a point, I do not recommend doing this since it would be very confusing and fragile)
public ABC() : this
(
(IMemoryCache) Activator.CreateInstance
(
Assembly.GetExecutingAssembly().GetTypes().First
(
t => typeof(IMemoryCache).IsAssignableFrom(t) && !t.IsInterface
)
)
)
{
}
The reflection code snippet above, in essence, what a dependency injection library would do, and you might want to consider using one if your project is suitable for it.
One last thing, just to have a complete answer, of course, you can also implement a body in your overloaded contractors:
public class ABC
{
private readonly ICache _cache;
public ABC()
{
_cache = new Cache();
}
public ABC(ICache cache)
{
_cache = cache;
}
}
: this() syntax is only required if you want to call other constructors in the same class for code reuse.

use instances not types. create an instance of what ever class fulfills your Interface.
public class ABC
{
private readonly IMemoryCache _cache;
private readonly IConfiguration _config;
private readonly IDistributedCache _distributedCache;
public ABC(IMemoryCache memoryCache, IConfiguration config, IDistributedCache distributedCache)
{
_cache = memoryCache;
_config = config;
_distributedCache = distributedCache;
}
public ABC() : this(new MemoryCache(), new Configuration(), new DistributedCache() )
{
}
}

Related

Repository/Service Pattern Issues .NET Core

Having some architecture issues that I'm trying to work through. I need to find a better way to do what I'm trying to do.
Below is a brief mockup of how my services/repos look. My problem is I am getting a circular reference when activating them. The problem is there is code in each service that I need for example in the LoadService I may need to trigger a method in the CustomerService and vice versa.
Need help to understand the best approach here. I am trying to get these services in a SRP as much as possible.
LoadRepository
public class LoadRepository
{
private readonly DBContext _DBContext;
public LoadRepository(DBContext DBContext)
{
_DBContext = DBContext;
}
public override DbSet<LoadEntity> LoadDbSet()
{
return _DBContext.Load;
}
}
LoadService
public class LoadService
{
private readonly LoadRepository _loadRepository;
private readonly ICustomerService _customerService;
public LoadService(
LoadRepository loadRepository,
ICustomerService customerService
)
{
_loadRepository = loadRepository;
_customerService = customerService;
}
}
CustomerRepository
public class CustomerRepository
{
private readonly DBContext _DBContext;
public CustomerRepository(DBContext DBContext)
{
_DBContext = DBContext;
}
public override DbSet<CustomerEntity> LoadDbSet()
{
return _DBContext.Customer;
}
}
CustomerService
public class CustomerService
{
private readonly CustomerRepository _customerRepository;
private readonly ILoadService _loadService;
public CustomerService(
CustomerRepository customerRepository,
ILoadService loadService
)
{
_customerRepository = customerRepository;
_loadService = loadService;
}
}
In my personal experience it is better to avoid dependencies on the same level referencing each other. Move common functionality into some helper classes and/or inject all needed repositories into the corresponding services. For example :
public class LoadService
{
private readonly LoadRepository _loadRepository;
private readonly CustomerRepository _customerRepository;
public LoadService(
LoadRepository loadRepository,
CustomerRepository customerRepository
)
{
_loadRepository = loadRepository;
_customerRepository = customerService;
}
}
Another approach to mitigate the problem (if currently refactoring is to much of headache) - use lazy injection via factories, for example something like the following using factory via Func:
// default DI does not provide automatic Func registration
Services.AddScoped<Func<ICustomerService>>(sp => () => sp.GetRequiredService<>(ICustomerService))
public class LoadService
{
private readonly LoadRepository _loadRepository;
private readonly Func<ICustomerService> _customerServiceFactory;
public LoadService(
LoadRepository loadRepository,
Func<ICustomerService> customerService
)
{
_loadRepository = loadRepository;
_customerServiceFactory = customerService;
}
}
And when it is needed invoke the factory - _customerServiceFactory().SomeMethod(). Though note that this method can result in SO if you have cycle in invocations (i.e. ICustomerService.Foo() calls ILoadService.Bar() which calls ICustomerService.Foo()) which can be caught only in runtime.

How can I avoid repeated derived class constructors that are identical to the base class?

I'm using .NET 7 Preview with ASP.NET to wrap a bunch of WCF services so they're REST. Each service has its own controller and I'm using dependency injection with the constructor.
Each WCF service is automatically generated with its own client and a couple methods that I use delegates on the base class (MyBaseController) to handle all the logic and things.
The problem is I need the injected dependencies, but if I change the base constructor, I have to modify 40+ derived classes.
Below is the basic concept I'm using, but ideally the derived classes would only contain delegate overrides and the class definition providing the generics.
You can see for derived classes A/B, I have to have a constructor.
Questions:
Is there another method of dependency injection where I don't have to declare them in the constructor? This would allow me to handle it in the base class and then keep a simple constructor in the derived classes.
Can I inherit the base constructor somehow? - I don't think there is with older versions of .NET so I was hoping .NET 7 might have some new magic I didn't know about.
Should I be moving all of my constructor needs into a service class and then just passing that everywhere to the controllers?
Code:
[ApiController]
[Route("[controller]")]
public abstract class MyBaseController<DerivedClient, MyRequest, MyResponse> : ControllerBase
where DerivedClient : HttpClient, new()
{
protected DerivedClient _derivedClient;
protected readonly ILogger _logger;
public IConfiguration _configuration;
protected IOptions<MyOptions> _options;
public abstract Func<MyRequest, Task<MyResponse>> MyClientDelegate { get; }
protected MyBaseController(ILogger<DerivedClient> logger, IOptions<MyOptions> options, IConfiguration configuration)
{
// I need these dependencies though, and with a simple constructor (i.e. MyBaseController()),
// I can't access them.
_derivedClient = new();
_logger = logger;
_options = options;
_configuration = configuration;
}
[HttpGet, Route("GetTheData")]
public Task<MyResponse> GetTheData(MyRequest request)
{
return MyClientDelegate(request);
}
}
public class A : MyBaseController<AClient, string, string>
{
// How can I avoid having this in every derived class when they're all essentially identical?
public A(ILogger<AClient> logger, IOptions<MyOptions> options, IConfiguration configuration) : base(logger, options, configuration) { }
// I only want my derived classes to have the delegate
public override Func<string, Task<string>> MyClientDelegate => _derivedClient.GetDataA;
}
public class B : MyBaseController<BClient, string, string>
{
// How can I avoid having this in every derived class when they're all essentially identical?
public B(ILogger<BClient> logger, IOptions<MyOptions> options, IConfiguration configuration) : base(logger, options, configuration){ }
// I only want my derived classes to have the delegate
public override Func<string, Task<string>> MyClientDelegate => _derivedClient.GetDataB;
}
public class AClient : HttpClient
{
public AClient() { }
public Task<string> GetDataA(string request)
{
return Task.FromResult($"A Request: {request}");
}
}
public class BClient : HttpClient
{
public BClient() { }
public Task<string> GetDataB(string request)
{
return Task.FromResult($"B Request: {request}");
}
}
I don't think there's a way to avoid having all the constructors with the same declarations.
I believe it's a language design decision, since depending on how it is implemented it could bring some other issues*, although I feel it would be nice to have some other way to do it.
A possible improvement might be to encapsulate all of your dependencies in a new class, so that would be the class injected everywhere. If any new dependency appears you'd only change that class.
Something like this:
public abstract class Base<DerivedClient> : where DerivedClient : HttpClient, new()
{
protected DependencyContainer _dependencyContainer;
protected DerivedClient _derivedClient;
protected MyBaseController(DependencyContainer<DerivedClient> dependencyContainer)
{
_dependencyContainer = dependencyContainer;
_derivedClient = new();
}
}
The DependencyContainer would be:
public class DependencyContainer<DerivedClient> : where DerivedClient : HttpClient
{
public readonly ILogger<DerivedClient> logger;
public IConfiguration configuration;
public IOptions<MyOptions> options;
public DependencyContainer(
ILogger<DerivedClient> logger,
IOptions<MyOptions> options,
IConfiguration configuration,
... future new ones)
{
this.logger = logger;
this.options = options;
this.configuration = configuration;
... future new ones
}
}
And every derived class would remain like this:
public A : Base<AClient>
{
public A(DependencyContainer<AClient> dependencyContainer) : base(dependencyContainer) { }
public void Method()
{
_dependencyContainer.logger.log(":)");
_dependencyContainer. ... all other dependencies ...
_derivedClient.GetDataA("test"); // Method from AClient is accessible because we inherit from Base<AClient>
}
}
Then you should remember to add the new DependencyContainer to the service collection in Program.cs:
builder.Services.AddScoped(typeof(DependencyContainer<>), typeof(DependencyContainer<>));
I don't love it, but it makes only one class change when you want to inject something new.
* I kept digging into this and found a comment in another question that links to a MSDN post that might explain this better

Dependency Injection resolution with constructors having multiple parameters whose values are determined at runtime .NET Core 3

As a reply to an earlier question (Accessing ILogger from non-Controller classes in Class Libary .NET Core 3), we can inject the dependent class into the controller. The DI Container resolves dependencies on registration of Transient services at the time of Startup. Hence if a ClassA is instantiated by a Controller, as a result of this mechanism, we can access ILogger in Class A.
Original question code sample:
public class Startup
{
...
public void ConfigureServices(IServiceCollection services)
{
services.AddLogging();
services.AddTransient<ClassX>();
...
}
}
public class ControllerB : ControllerBase
{
private readonly ClassX classX;
private readonly ILogger logger;
public ControllerB(ClassX classX, ILogger<ControllerB> logger)
{
this.classX = classX;
this.logger = logger;
}
...
}
public class ClassX
{
private readonly ILogger logger;
public ClassX(ILogger<ClassX> logger)
{
this.logger = logger;
}
}
Now I have a scenario as below, where the constructor of ClassX has multiple parameters:
public class ClassX
{
private readonly ILogger logger;
private int _num1;
public ClassX(ILogger<ClassX> logger, int num1)
{
this.logger = logger;
this.num1 = num1;
}
}
Constructor of ClassX made available to .NET Core DI container through [ActivatorUtilitiesConstructor]:
[ActivatorUtilitiesConstructor]
public ClassX(int num)
{
this.constructorNum = num;
}
So we need to inject the constructor parameters during DI resolution at Startup. I tried this
services.AddTransient<Func<int, ClassX>>((provider) =>
{
return new Func<int, ClassX>((numParam) => new ClassX(numParam));
});
But this throws an error as we are not passing the ILogger.
How do I inject the ILogger as well as the constructor parameters at runtime through DI?
For this scenario, you can use the provider parameter that's being passed into the factory function to resolve an instance of ILogger<ClassX> from the IoC container:
services.AddTransient<Func<int, ClassX>>((provider) =>
{
return new Func<int, ClassX>((numParam) =>
new ClassX(provider.GetRequiredService<ILogger<ClassX>>(), numParam));
});
provider here is an implementation of IServiceProvider. This example uses an extension method, GetRequiredService, to retrieve an instance of ILogger<ClassX>.

C# generics basic knowledge?

I have following two classes
public class CommandFetcher : ICommandFetcher
{
private readonly Dictionary<TypeAndVersion, Type> _configuration;
public CommandFetcher(Dictionary<TypeAndVersion, Type> configuration)
{
_configuration = configuration;
}
public ICommand FetchFrom(MessageEnvelope messageEnvelope)
{
TypeAndVersion typeAndVersion = new TypeAndVersion(messageEnvelope.MetaData.MessageType,
messageEnvelope.MetaData.MessageTypeVersion);
return (ICommand)JsonConvert.DeserializeObject(messageEnvelope.MessageData, _configuration[typeAndVersion]);
}
}
and
public class MessageDeserializer : IMessageDeserializer
{
private readonly IDictionary<TypeAndVersion, Type> _configuration;
public MessageDeserializer(IDictionary<TypeAndVersion, Type> configuration)
{
_configuration = configuration;
}
public IMessage Deserialize(string messageData, IMetaData metaData)
{
var typeAndVersion = new TypeAndVersion(metaData.MessageType, metaData.MessageTypeVersion);
if (!_configuration.ContainsKey(typeAndVersion))
throw new InvalidOperationException("Invalid version");
return (IMessage) JsonConvert.DeserializeObject(messageData, _configuration[typeAndVersion]);
}
}
i rewrite the configuration part in both class
but now i want to get that configuration from MessageDeserializer class into CommandFetcher class
how can i do it ?
Thank you !
No idea if I am reading your question correctly...but it sounds like you are wanting to instantiate a CommandFetcher from within the MessageDesrializer?? If this is correct you could try making the Dictionary on the CommandFetcher an IDictionary instead of a Dictionary
There are multiple problems in your question:
You are not saying anything about the dependencies between the classes. Does one use the other?
You are not sharing what configuration actually is. Does each class need their own configuration?
So here is my guess: Your two classes actually use the same _configuration. In that case, this has nothing to do with generics. All you need to do is pass the same Dictionary to both object constructors.
If you are attempting to make a single generic method that handles both those cases it would look something like this:
public class GenericDeserializer<T> : IGenericDeserializer
{
private readonly IDictionary<TypeAndVersion, Type> _configuration;
public GenericDeserializer(IDictionary<TypeAndVersion, Type> configuration)
{
_configuration = configuration;
}
public T Deserialize(string messageData, IMetaData metaData)
{
var typeAndVersion = new TypeAndVersion(metaData.MessageType, metaData.MessageTypeVersion);
if (!_configuration.ContainsKey(typeAndVersion))
throw new InvalidOperationException("Invalid version");
return (T)JsonConvert.DeserializeObject(messageData, _configuration[typeAndVersion]);
}
}
That said, you would need to normalize ICommand and IMessage as well as create a generic interface for ICommandFetcher and IMessageDeserializer.

Castle Windsor - passing Type as constructor parameter

I have a class that takes Type as a constructor parameter. How can I register this in the Windsor container?
public Class NLogLogger : ILogger
{
private NLog.Logger _logger;
public NLogLogger(Type type)
{
_logger = NLog.LogManager.GetLogger(type.FullName);
}
...
}
I am trying to register it this way:
container.Register(Component.For(typeof(ILogger))
.ImplementedBy(typeof(NLogLogger))
.LifestyleTransient()
.DependsOn(new Hashtable
{
{"type", ???}
}));
I need to fill in the ???. I could not figure out how I can pass the calling class's Type there.
Update
Going by your update you want to inject the type so that you can use it for logging. There are two solutions.
public class ClassDependentOnLogger
{
private ILogger _logger;
public ClassDependentOnLogger(ILogger logger)
{
_logger = logger;
}
....
}
1 - Use a Windsor SubDependancyResolver. The example below shows how to return and instance of an ILog but you could easily adapt it to return a Type instead if that is what you wanted to do:
public class LoggerResolver : ISubDependencyResolver
{
private readonly IKernel kernel;
public LoggerResolver( IKernel kernel )
{
this.kernel = kernel;
}
public object Resolve( CreationContext context, ISubDependencyResolver contextHandlerResolver, Castle.Core.ComponentModel model, DependencyModel dependency )
{
return NLog.LogManager.GetLogger(model.Implementation.FullName);
}
public bool CanResolve( CreationContext context, ISubDependencyResolver contextHandlerResolver, Castle.Core.ComponentModel model, DependencyModel dependency )
{
return dependency.TargetType == typeof( ILogger );
}
}
//Register the sub dependency resolver. This looks cleaner if you do it via a
//Facility but that's a whole other class
Container.Kernel.Resolver.AddSubResolver( new LoggerResolver( Kernel ) );
2 - Use the Windsor LoggingFacility
There is no need for the NLoggerClass described in your example.

Categories

Resources