I have an azure application developed using MVC Web API, and it uses Ninject as the dependency injection framework, here there are number of queues used to communicate with the other worker roles responsible for the background processing.
To be able to unit test I decided to wrap the QueueClient with class called QueueClientWrapper and use an interface named IQueueClientWrapper
the class and interface looks like follows,
public interface IQueueClientWrapper
{
void Send<T>(T message);
}
public class QueueClientWrapper : IQueueClientWrapper
{
private QueueClient _queueClient;
public QueueClientWrapper(QueueClient queueClient)
{
_queueClient = queueClient;
}
public void Send<T>(T message)
{
_queueClient.Send(new BrokeredMessage(message));
}
}
However the limitation of this approach is I need to pass the QueueClient into the constructor, which is not possible with the Ninject.
So I was thinking changing the interface like,
public interface IQueueClientWrapper
{
void Send<T>(string connectionString,string queueName,T message);
}
so that I can use Ninject to inject the QueueClientWrapper without needing to pass constructor argument,
The issue I have now is, usually it's not recommended to create multiple queue client objects and we have to re-use same instance. So what's the best way to address this (I thought of using a static Hashtable and use to store queue name, queue client pairs, but I'm not very happy with that approach either)?
Dealing with Dependency Injection and Azure Queue
This question is from 2014, but here is a 2022 answer
You will need these 2 official azure extensions :
Azure.Storage.Queues (Contains the queue service)
Microsoft.Azure.Functions.Extensions (Contains helpers for the Startup.cs)
Add this line to your Startup.cs in the Configure method :
builder.Services.AddAzureClients(builder =>
{
builder.AddQueueServiceClient(configuration.GetValue<string>("AzureWebJobsStorage"));
});
And the constructor where you want the service :
public QueueHandlingService(QueueServiceClient queueClient)
{
_queueClient = queueClient;
//Or _queueClient = queueClient.GetQueueClient("myqueue-items");
}
Here are the docs for :
AddAzureClients
AddQueueServiceClient
Related
I have a multi tenant system with background job. The tenancy details are stored in database and based on the tenant adding request in service bus, I want to resolve the dependencies based on tenant.
For this I would have to add dependencies to service collection before creating scope. When trying to inject IServiceCollection, it gives me error.
I am looking for the best way to inject dependencies from HostedService
public async Task MessageHandler(object sender, Message message)
{
// Inject dependencies
services.AddScoped<IMyService,Myservice>(); // No way to get services here
using (var scope = serviceProvider.CreateScope())
{
var ... = scope.ServiceProvider.GetService<...>();
//...
}
}
I had a similar need a while back. I created my own service bus handler.
You could try something like the below, where you inject a service (here as an example I'm using IMessageService) to the ServiceeBusHandler that itself has a dbcontext injected.
Then where ever you implement IServiceBusHandler you can specify for which tenant (and their queues) you want the connection built.
public class ServiceBusHandler : IServiceBusHandler
{
private readonly ServiceBusSender _serviceBusSender;
private readonly IMessageService _messageService;
public ServiceBusHandler(
ServiceBusSender serviceBusSender,
IMessageService messageService)
{
_serviceBusSender = serviceBusSender;
_messageService = messageService;
}
public async Task PublishMessageAsync<T>(T message)
{
var jsonString = JsonConvert.SerializeObject(message);
var serviceBusMessage = new ServiceBusMessage(jsonString);
await _serviceBusSender.SendMessageAsync(serviceBusMessage);
}
internal static IServiceBusHandler Create(ServiceBusSender sender)
{
return new ServiceBusHandler(sender);
}
}
public class ServiceBusHandlerFactory : IServiceBusHandlerFactory
{
private readonly IAzureClientFactory<ServiceBusClient> _serviceBusClientFactory;
public ServiceBusHandlerFactory(
IAzureClientFactory<ServiceBusClient> serviceBusClientFactory)
{
_serviceBusClientFactory = serviceBusClientFactory;
}
public IServiceBusHandler GetClient(string tenantId)
{
var tenantDetails = _messageService.GetTenantDetails(tenantId); // Call to your DB to get details about the Tenant
var client = GetServiceBusClient(tenantDetails.QueueName);
var sender = client.CreateSender(tenantDetails.QueueName);
return ServiceBusHandler.Create(sender);
}
protected virtual ServiceBusClient GetServiceBusClient(string queueName)
{
var client = _serviceBusClientFactory.CreateClient(queueName);
return client;
}
}
What you are trying to achieve is to change the set of registrations after the Container was built. MS.DI does not support this, and while historically, more mature DI Containers tended to support this behavior, most modern DI Containers stopped supporting this, because there are too many negative consequences in allowing this. Autofac, for instance, obsoleted its Update method in 2016 and described the issues with updating the Container in details. Ninject has gone through a similar process, although development stopped before the final release that removed the possibility to update the Container. The Simple Injector DI Container never supported updating, and its documentation has some clear texts that describe what the issue is.
You might find a DI Container that supports this, but I would urge you to abbondon this path, because of the negative consequences that it can (and probably will) cause, as the previous links described.
Instead, you will have to find a different way to get tenant-specific behavior, with one single set of registrations. The trick here, typically lies in creating a Proxy implementation of your IMyService that can forward the call to the correct tenant implementation.
This might look something like this:
public class ProxyMyService : IMyService
{
public IMyService Service { get; set; }
// IMyService methods
public void SomeMethod() => this.Service.SomeMethod();
}
This proxy class can be registered at startup, together with other IMyService implementations, as follows:
services.AddScoped<IMyService, ProxyMyService>();
services.AddTransient<MyServiceTenant1>();
services.AddTransient<DefaultMyServiceTenant>();
With this, your hosted service can become the following:
private ProxyMyService service;
public MyHostedService(IMyService service)
{
this.service = (ProxyMyService)service;
}
public async Task MessageHandler(object sender, Message message)
{
using (var scope = serviceProvider.CreateScope())
{
var p = scope.ServiceProvider;
var proxy = (ProxyMyService)p.GetRequiredService<IMyService>();
proxy.Service = IsTentant1
? p.GetRequiredService<MyServiceTenant1>()
: p.GetRequiredService<DefaultMyServiceTenant>();
var ... = p.GetRequiredService<...>();
//...
}
}
A more evolved solution would entail a Proxy implementation that allows to switch between tenant-specific implementations internally. That would likely mean moving part of the logic that's currently inside MessageHandler into the ProxyMyService.
Do notice that the solutions I suggested do not require an abstract factory. Abstract factories are typically not needed.
Core issue
Every example I see for dependency injection is paired with MVC for some reason as if nothing else exists outside of web projects. I take issue with this because there is a contradiction going on with MVC utilizing dependency injection but it delivers those dependencies through a Dependency Resolver which to me is just another name for a Service Locator.
DI in a simple console application
With all that being said, how do you use DI with a simple console application?
When there isn't a convenient Dependency Resolver ready to use. How do I actually perform the injection part of DI?
I see the disapproving tone around Service Locators, but what else can you do?
You cannot pass the container because that's also bad practice, but again what else can be done?
Common confusion/frustration
I see a lot of programmers making these mistakes and honestly I can't blame them for it. There isn't a clear solution outside of MVC which is clearly using the dreaded Service Locator.
DI introduces its own problems
Something I don't feel good about doing is pass a dependency through a chain of objects to use it in a deeply nested piece of code. This just feels wrong.
Example
This is a watered down example of something I am working on to demonstrate my concern. I don't like passing the SMTP client dependency through a class, just to give it to another class. You might be compelled to say "Inject the SmtpClient into ServiceClass then into EntryPoint". In my example I cannot inject ServiceClass because it actually comes from a Factory pattern.
public static void Main(string[] args)
{
var smtpClient = _container.GetDependency<ISmtpClient>();
//When I do this manually I feel like it defeats the purpose of DI
var ep = new EntryPoint(smtpClient);
ep.RunAProcess();
}
public class EntryPoint
{
private readonly ISmtpClient _smtpClient;
public EntryPoint(ISmtpClient smtpClient)
{
//EntryPoint doesn't use this dependency
_smtpClient = smtpClient;
}
public void RunAProcess()
{
/* More code here */
//ServiceClass actually comes from a Factory, but I didn't
//want to make this example too long
var svc = new ServiceClass(_smtpClient);
svc.Send();
}
}
public class ServiceClass
{
private readonly ISmtpClient _smtpClient;
public ServiceClass(ISmtpClient smtpClient)
{
//ServiceClass uses this dependency
_smtpClient = smtpClient;
}
public void Send()
{
using (var mail = CreateMailMessage(message))
{
_smtpClient.Send(mail);
}
}
}
Almost related existing question
This is the closest SO question I found in relation to my query:
DbContext Dependency Injection outside of MVC project
Outside of MVC you can use HostBuilder see https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-2.2
The general idea is that it works pretty much like the web version ( and will support console, windows services, and linux daemons etc )
public static async Task Main(string[] args)
{
var host = new HostBuilder() .
.ConfigureServices(ConfigureServices)
.UseConsoleLifetime()
.Build();
await host.RunAsync();
}
private static void ConfigureServices(HostBuilderContext context, IServiceCollection services)
{
services
.AddTransient<IThing, Thingy>()
.AddTransient<Stuff>()
.AddHostedService<MyService>();
}
Your Hosted Service is like your main entry point and things from there will be injected....
internal class MyService : IHostedService
{
public MyService(Stuff stuff) // injected stuff
{
}
public Task StartAsync(CancellationToken cancellationToken)
{
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
This is more a matter of misunderstanding the design principles.
Something I don't feel good about passing a dependency through a chain of objects to use it in a deeply nested piece of code. This just feels wrong.
The core of your issue is about understanding how to apply a clean design which allows loose coupling and high cohesion. Whether it is Asp.Net MVC or console application is an implementation detail.
The watered down example in this case is not following a clean design as EntryPoint is tightly coupling to ServiceClass and also violates the Explicit Dependencies Principle.
EntryPoint in this example is not being genuine about its dependencies. If it does not use ISmtpClient directly then it should not explicitly depend on it just to pass it on.
And if ServiceClass is coming from a factory then the factory should be applied at the composition root and then explicitly injected into EntryPoint
Review the following refactoring to see what I am referring to
public static void Main(string[] args) {
//ISmtpClient should be injected into ServiceClass
//when resolved by the container or factoty
IService service = _container.GetDependency<IService>();
var ep = new EntryPoint(service);
ep.RunAProcess();
}
public class EntryPoint {
private readonly IService service;
public EntryPoint(IService service) {
this.service = service;
}
public void RunAProcess() {
/* More code here */
service.Send(message);
}
}
public class ServiceClass : IService {
private readonly ISmtpClient _smtpClient;
public ServiceClass(ISmtpClient smtpClient) {
//ServiceClass uses this dependency
_smtpClient = smtpClient;
}
public void Send(Message message) {
using (var mail = CreateMailMessage(message)) {
_smtpClient.Send(mail);
}
}
}
So even if you apply pure dependency injection at the composition root, only the actual dependencies are injected into the target dependent.
I'm making an application that uses an external API. But I don't want my application to be dependant on the API. So I have been reading about how to achieve this. I read that the thing I want is loose coupling. I want to loosely couple my class that uses the external API from the rest of my application. My question is how do I achieve this. If read about different design patterns, I can't find one that helps with my problem.
public class GoogleCalendarService
{
private const string CalendarId = ".....";
private CalendarService Authenticate(string calendarId)
{
...
}
public void Create(Booking newBooking, string userId)
{
...
InsertEvent(newEvent, userId);
}
private void Insert(Event newEvent, string userId)
{
call authenticate account
....
}
public List<Booking> GetEvents()
{
call authenticate account
...
}
}
Above is my code for the class that uses the external API. In the rest of my application I use this class the following way:
public class MyApplication
{
private void MyFunction()
{
GoogleCalendarService googleCalendarService = new GoogleCalendarService();
googleCalendarService.CreateEvent(..., ...)
}
}
I do this on multiple places in my application. So my question is: How can I loosely couple the API class from the rest?
Edit: I probably want a general calendar service interface that makes it easier to replace the google calendar service with an other calendar service when needed.
that makes it easier to replace the google calendar service with an other calendar service
The main pattern you will want to look at is Adapter. But you would want to use that in combination with Dependency Injection.
The DI first:
public class MyApplication
{
// constructor injection
private IGeneralCalendarService _calendarService;
public MyApplication(IGeneralCalendarService calendarService)
{
_calendarService = calendarService;
}
private void MyFunction()
{
_calendarService.CreateEvent(..., ...)
}
}
And the Adapter would look something like
public class GoogleCalendarServiceAdapter : IGeneralCalendarService
{
// implement the interface by calliong the Google API.
}
In addition you will need generic classes for Event etc. They belong to the same layer as the interface.
You need to write a wrapper around that API. And rewrite every Output/Input of that API with your wrapper IO. And after that, you can take advantage of Dependancy Injection to use your own code. By this way you can have an abstraction layer around that API
I have
Public Class AuthorBLL : IAuthorBLL
{
Public Add_Author();
Public Get_AuthorsList();
}
Public Class BookBLL : IBookBLL
{
Public Add_Book();
Public Get_BookList();
}
Now I want to call my Business logic layer methods in my WCF layer and want to expose similar WCF OperationContracts methods to the UI.
My WCF class looks like this:
Public class WCFService : IWCFService
{
private IAuthorBLL _authorBLL;
private IBookBLL _BookBLL;
public WCFService(IAuthorBLL authorBll, IBookBLL bookBll)
{
_authorBLL = authorBll;
_bookBll = bookBll;
}
Public WCF_Add_Author (serializable_author author);
{
_authorBLL.Add_Author();
}
Public WCF_Get_AuthorsList()
{
_authorBLL.Get_AuthorList();
}
Public WCF_Add_Book (serializable_book book);
{
_bookBll.Add_Book();
}
Public WCF_Get_BookList()
{
_bookBll.Get_BookList();
}
}
Question:
My question is regarding the WCF constructor where i have to pass all these Business logic layer objects as constructor parameters to achieve DI. How can i make it generic so that if in the future I have publisherBLL, VentorBLL, CustomerBLL and so on... i don’t have to pass them all in the WCF constructor?
I know it’s the way dependency injection works but what if i have 50 BLL objects; will i have to pass them all in the WCF constructor. Is there any way to avoid it? Any design pattern or technique which can give me better solution to this.
I need to keep one WCF service which can expose all method whether its Authors, books, publishers, clients, customers or retailers. One service should expose all CRUD methods.
EDit:
As you are saying use Ninjet or CastleWinsor for IOC where you can create the containers to define DI. but still you have to define the constructor based parameters in the WCF constructor in WCF class.
Do we will have to define the constructor parameters as below. or if the WCF is too big to expose so many methods then what is a solution for an application where you have to do CRUD for Authors, books, employees (working in a shop), publishers, HR and payroll modules. every module have webpages and calling WCF service to do CRUD. as we never know when we will need to move on to Mobile interface or how many other applications will use the same methods so we want to expose all through WCF service. What should i do?
private IAuthorBLL _authorBLL;
private IBookBLL _BookBLL;
private IClientBll _ClientBll;
private IPublisherBll _PublisherBll;
private IHRBll _HRBll;
private IEmployeeBll _employeeBll;
public WCFService(IAuthorBLL authorBll, IBookBLL bookBll, IClientBll
clientBll, IPublisherBll publisherBll, IEmployeeBll
employeeBll, IHRBll HRBll)
{
_authorBLL = authorBll;
_bookBll = bookBll;
_authorBLL = authorBll;
_ClientBll = clientBll;
_PublisherBLL = publisherBll;
_HRBll = HrBll;
_EmployeeBLL = EmployeeBll;
}
As i have so many front end pages to deal with employees, authors, clients, books, publishers. What should i do.
You've pretty much answered yourself. If you use some DI framework like Unity or Ninject then you won't have to bother about passing 50 arguments to your constructor - just retrieve the service object from the DI framework's factory and it will care about providing appropriate arguments. Maybe what are you missing is that you can register your service in the DI framework along with it's dependencies.
Simple example with Unity:
In some kind of a Bootstrapper class which initializes whole application:
public void Run()
{
//...
SetupContainer();
//...
RunWebService();
//...
}
public void SetupContainer()
{
//This can also be done using a configuration file
this.container.RegisterType<IAuthorBLL, AuthorBLLImpl>();
this.container.RegisterType<IBookBLL, BookBLLImpl>();
this.container.RegisterType<IOther1BLL, Other1BLLImpl>();
//...
this.container.RegisterType<IOther50BLL, Other50BLLImpl>();
}
public void RunWebService()
{
this.container.RegisterType<IWCFService, WCFService>(
new ContainerControlledLifetimeManager());
var serviceSingleton = this.container.Resolve<IWCFService>();
//... proceed with service setup and run
}
Note that usually SetupContainer is split between different modules. Each of them registers its own classes.
I'm struggling to find a way forward here.
I have a VB6 screen, which i need to call a .Net 'adapter' component, which calls out to a WCF service.
The WCF service is under windows authentication as i want to detect the windows logon of the user calling the functionality.
The service reference is in the .Net adapter. To get this to work i have had to add detail to a binding, specifying the security, which all works fine in the real world.
My problem is unit testing this, and trying to mock the call to the WCFServiceClient. Because i am using a parametrised constructor, Moq will not mock it. So i believe that my mock is therefore not being used, and a real call is going through to the WCF layer when i run my unit test (it is, i put a break point in the wcf service running locally in my solution).
To simplify my code i've pasted a BasicHttpBinding in, as the problem isnt the security, its how do i recode the function so i can mock the call, or can i do something else allowing me to mock the call?
In the .Net adapter, in the function i am calling i have the following code
using (var myWcfService = new MyWcfServiceClient(new BasicHttpBinding (), GetEndpointAddress()))
{
//do stuff here
}
In my unit test i have the following mock setup
var mockMyWcfService = new Mock<IMyWcfService>();
Which is not creating a mock that gets used by the above code.
If i put parameter types into the constructor, that does not work either as Moq will only mock an interface, and a default empty constructor (i believe , from googling my previous error)
Also, although in other projects in the solution we use Unity for IOC, i do not believe i can do that in this project as the .Net adapter is called from a VB6 app, which has no app.config for me to specify all of the unity config.
Thanks
If I understand it correctly, you have a class that uses a MyWcfServiceClient() and you want to control it's lifetime within your class (ergo the using block) therefore you cannot pass in a mocked service.
e.g.
public interface IMyWcfService {
void DoSomething();
}
public class MyClass {
private readonly IMyWcfService myService;
public MyClass(IMyWcfService myService) {
this.myService = myService;
}
public void DoIt() {
myService.DoSomething();
}
}
What you can try is to use a provider to create the service and pass this in and use a default provider to generate the service when not unit testing.
e.g.
public interface IService : IDisposable {
}
public class DefaultService : IService {
public void Dispose() {
}
}
public interface IServiceProvider {
IService GetService();
}
public class DefaultServiceProvider : IServiceProvider {
public IService GetService() {
return new DefaultService();
}
}
public class Consumer {
private readonly IServiceProvider serviceProvider;
public Consumer() : this (new DefaultServiceProvider()){
}
internal Consumer(IServiceProvider serviceProvider) {
this.serviceProvider = serviceProvider;
}
public void DoIt() {
using (var service = serviceProvider.GetService()) {
// do stuff
}
}
}
I generally make the unit test constructors internal - personal preference, not required.
In the unit test you can create a mock provider that returns a mock service.