Example of using Shared Services. Prism - c#

I have 5 modules and I am using EventAggregator pattern to communicate between modules. And it seems to me that my code becomes ugly and it is bad design to use EventAggregator in my project.
There are three ways to communicate between modules:
Loosely coupled events
Shared services
Shared resources
I would like to know more about communication by Shared Services. What I've found is an article about StockTrader application from Prism ToolKit.
Is there some more lightweight and clearer example of using Shared Services in Prism where it is possible to see talking between modules using Shared Services? (downloadable code would be highly appreciated)

In which way is your code getting ugly? The EventAggregator is a shared service, if you like.
You put a service interface in a shared assembly, and then one module can, say, push data into the service while another module get's the data from the service.
Edit:
Shared assembly
public interface IMySharedService
{
void AddData( object newData );
object GetData();
event System.Action<object> DataArrived;
}
First communicating module
// this class has to be resolved from the unity container, perhaps via AutoWireViewModel
internal class SomeClass
{
public SomeClass( IMySharedService sharedService )
{
_sharedService = sharedService;
}
public void PerformImport( IEnumerable data )
{
foreach (var item in data)
_sharedService.AddData( item );
}
private readonly IMySharedService _sharedService;
}
Second communicating module
// this class has to be resolved from the same unity container as SomeClass (see above)
internal class SomeOtherClass
{
public SomeOtherClass( IMySharedService sharedService )
{
_sharedService = sharedService;
_sharedService.DataArrived += OnNewData;
}
public void ProcessData()
{
var item = _sharedService.GetData();
if (item == null)
return;
// Do something with the item...
}
private readonly IMySharedService _sharedService;
private void OnNewData( object item )
{
// Do something with the item...
}
}
Some other module's initialization
// this provides the instance of the shared service that will be injected in SomeClass and SomeOtherClass
_unityContainer.RegisterType<IMySharedService,MySharedServiceImplementation>( new ContainerControlledLifetimeManager() );

The Prism Library repo on GitHub has an up to date version of the Stock Trader sample application, which includes service examples and source code for you to look at, and download.
https://github.com/PrismLibrary/Prism-Samples-Wpf/tree/master/StockTraderRI

Related

How does one use dependency injection outside of an MVC context?

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.

Loosely coupling class

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

Azure Queue client Dependency injection

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

WCF and DI and Business logic layer, How to expose all methods of BLL, Best practice

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.

How to inject N MEF exports into 1 Unity composite service using MefContrib or other technique?

Let's say I have 5 separate assemblies with the following (assume the class name is different in each):
[Export(typeof(IService))]
public class Service: IService
{
// ...
}
And I have a class that will be a composite of these in my main assembly
public class CompositeService : IService
{
public CompositeService(IEnumerable<IService> services)
{
// ...
}
}
What I would like to do is have the Unity container resolve the CompositeService for the IService and have the MefContrib extension for Unity go and find the 5 other exports and inject them into CompositeService's constructor.
The problem is that you can't have N instances for a nameless unityContainer.RegisterType<IService> nor can you for named instances if they all have the same name.
I think I'm missing something simple in the combination of the 2 technologies (Unity + MEF) via the third (MefContrib) but can't seem to pick up on what it is.
Is this possible or is there a workaround? Eventually, I'm going for full bi-directional dependency injection and dynamic component discovery.
I think what is likely the best approach is to flip this around. Instead of trying to register your components via Unity, you actually leave the discovery of these parts to MEF. MEFContrib includes an Unity integration mechanism that allows your MEF composed parts to be injected into Unity components. This was original detailed at Piotr WŁodek's blog, whereby he also gives you a sample. Essentialy, the way it works is you can use a series of extension methods on your UnityContainer to register your catalogs. Internally, it will create the appropriate extension and wire up your container.
Here is a quick and dirty example, we'll create some interfaces:
public interface IUnityComponent
{
IEnumerable<IMefComponent> MefComponents { get; }
}
public interface IMefComponent
{
string Name { get; }
}
And then some sample parts which we'll export (via MEF):
[Export(typeof(IMefComponent))]
public class MefComponent1 : IMefComponent
{
public string Name { get { return "MEF Component 1"; } }
}
[Export(typeof(IMefComponent))]
public class MefComponent2 : IMefComponent
{
public string Name { get { return "MEF Component 2"; } }
}
Now, we'll create another part (this will be created via Unity):
public class UnityComponent : IUnityComponent
{
public UnityComponent(IEnumerable<IMefComponent> mefComponents)
{
// mefComponents should be provided from your MEF container.
MefComponents = mefComponents;
}
public IEnumerable<IMefComponent> MefComponents { get; private set; }
}
To wire it all up, we simply need to use the RegisterCatalog extension method on your UnityContainer (import MefContrib.Integration.Unity after you've added a reference to MEFContrib):
var container = new UnityContainer();
// Register the catalog - this handles MEF integration.
container.RegisterCatalog(new DirectoryCatalog("."));
// Register our Unity components.
container.RegisterType<IUnityComponent, UnityComponent>(new ContainerControlledLifetimeManager());
Now you should be able to grab the instance and enumerate the MEF-provided parts:
// Grab an instance of our component.
var instance = container.Resolve<IUnityComponent>();
foreach (var mefComponent in instance.MefComponents)
{
Console.WriteLine(mefComponent.Name);
}
note: 100% untested.
Just tried the same solution from Matthew here and it is working ok, Unity is picking up the exports from MEF and injecting them into the constructor (which accepts an IEnumerable<>).
Don't know if it can help you, but including both MefContrib and MefContrib.Integration.Unity can help: for a while I only had the latter included and encountered similar errors.
As a side note, keep in mind that all the registrations in Unity (coming from MEF exports) will be "nameless" so if you try ResolveAll<> you will get an empty collection and if you try Resolve<> you will get an exception if there is more than 1 implementation registered.

Categories

Resources