C# MVVM Handling and Passing UserID to different Models and ViewModels - c#

My current implementation of passing UserID in my application is through the constructor.
i.e. SomeObject s = new SomeObject(userID)
Where in there is a code behind that does things based on the userID. The userID is further keep tracked by adding another property named "CurrentUser", however this seems to be a dirty solution as I have to implement it to all ViewModels and it seems to violate the "DRY" concept.
The second approach I have in mind is creating a public static variable on my MainWindowViewModel where all my other models can refer to it as MainWindowViewModel.CurrentUser.
Is one of the two approach the correct way to do this or is there a better approach that i don't know about?

You need to carefully analyze up front what you want to achieve with your application. Are you happy with there only ever being one selected client? Or will you need to have multiple clients being viewed or edited at a time (i.e. you have an MDI style app)?
Going with the single client approach is easy, you can implement the global property bag as already mentioned in other answers. But I will advise caution: if you build your app on the assumption there will only ever be one selected client it becomes a real PITA to try to refactor to make it multi-client capable. Using a centralized property bag or "session service" like this is indeed decoupling state from the VM, but the centralized service can still turn into a monstrosity over time and you build up too much dependence on it.
If you do want to go the multi-client route, then you are on the right track - but instead of passing a client identifier in on the constructor, pass (inject) the entire client data object. The chances are that you already have most of the client details available from the piece of UI that invokes the client oriented VM, so pass it in and save having to make another trip to your database to get the details.

Don't tie a current user to a ViewModel. I typically opt for a SessionService of some kind. If you're using Dependency Injection (DI), register a singleton of an ISessionService and concrete implementation. If your not using DI, then just have your app start create a singleton, like a SessionService.Current. Then you can put any items you need in here. Then each ViewModel can ask for the SessionService.Current.User and they have it. Your ViewModels shouldn't know about each other, but they can know about services. This keeps it DRY and loosely coupled, especially if you only access these session variables using the interface of an ISessionService and not the concrete implementation. This allows you to mock one up very easily without changing any ViewModel code.

What you have here is the problem of Communication between ViewModels. There are a number of solutions but my fave is the Mediator Pattern:
using System;
namespace UnitTestProject2
{
public class GetDataViewModel
{
IMediator mediator;
public GetDataViewModel(IMediator mediator)
{
this.mediator = mediator;
this.mediator.ListenFor("LoggedIn", LoggedIn);
}
protected string UserId;
protected void LoggedIn(Object sender, EventArgs e)
{
UserId = sender.ToString();
}
}
public class LoginViewModel
{
IMediator mediator;
public LoginViewModel(IMediator mediator)
{
this.mediator = mediator;
}
public string UserId { get; set; }
public void Login(string userid)
{
this.UserId = userid;
this.mediator.RaiseEvent("LoggedIn", this.UserId);
}
}
public interface IMediator
{
public void ListenFor(string eventName, EventHandler action );
public void RaiseEvent(string eventName, object data);
}
}
I Haven't implemented the Mediator here, because it can get quite involved and there are a number of packages available. but you can see the idea from my simple interface. Essentially the Mediator provides a Global list of EventHandlers which any Viewmodel can call or add to. You still have the problem of where to store the event names. Its nice to have these in enums, but that gives you a coupling problem. (a problem I usually ignore)
Alternatively you can have a Controller or (MasterViewModel if you love MVVM)
using System;
namespace UnitTestProject3
{
public class GetDataViewModel
{
protected string UserId;
public void LoggedIn(Object sender, EventArgs e)
{
UserId = sender.ToString();
}
}
public class LoginViewModel
{
public EventHandler OnLogin;
public string UserId { get; set; }
public void Login(string userid)
{
this.UserId = userid;
if (this.OnLogin != null)
{
this.OnLogin(this.UserId, null);
}
}
}
public class Controller // or MasterViewModel
{
public void SetUp()
{
GetDataViewModel vm1 = new GetDataViewModel();
LoginViewModel vm2 = new LoginViewModel();
vm2.OnLogin += vm1.LoggedIn;
//wire up to views and display
}
}
}

Related

Validation in Business Layer: How to call service methods?

I have created a struct on validating models on Business Layer which is based on Steven's answer.
It is working well but something confuses my mind. I inject UserService in CreateUserValidator to able to use GetUser method. This means I call validator in UserService and create a new UserService instance to check whether user exist.
UserService -> [ValidateUser -> new UserService().GetUser()]
It works but seems to be a very bad design. But I have to use that method.
Could you please let me know how I can solve this problem, or Shouldn't I worry about it?
public class CreateUser
{
public string Name { get; set; }
public string Email { get; set; }
}
public sealed class CreateUserValidator : Validator<CreateUser>
{
private IUserService _userService;
public CreateUserValidator(IUserService userService)
{
_userService = userService;
}
protected override IEnumerable<ValidationResult> Validate(
CreateUser entity)
{
var user = _userService.GetUserByEmail(entity.Email);
if (user != null)
{
yield return new ValidationResult("Email", "Email address is already exist!");
}
}
}
UserService.cs
public partial class UserService : IUserService
{
IGenericUnitofWork _uow = null;
private readonly IValidationProvider _validationProvider;
public UserService(IGenericUnitofWork uow, IValidationProvider validationProvider)
{
_uow = uow;
_validationProvider = validationProvider;
}
public User CreateUser(CreateUser createUser)
{
this._validationProvider.Validate(createUser);
var user = new User()
{
Email = createUser.Email,
Name = createUser.Name,
};
_uow.Repository<User>().Insert(User);
_uow.SaveChanges();
return user;
}
public User GetUser(string email)
{
var user = _uow.Repository<User>().Where(m => m.Email == email).FirstOrDefault();
return user;
}
}
You dependency graph is cyclic. As described in section 6.3 of Dependency Injection in .NET second edition, dependency cycles are often caused by Single Responsibility Principle violations, as is the case in your design.
The problem is that UserService has too many responsibilities: Creating a user is a different responsibility than getting a user. Creating a user can become a very complex use case, as the validation logic hints at, while getting a user is something typically quite simple. It would therefore be beneficial to split UserService into multiple smaller classes. This would allow the validator to depend on the service that allows retrieving the user by its mail address, while the 'create user' service can depend on the validator.
To take it even one step further, you might want to remove validation from the 'create user' service completely. Validation is a cross-cutting concern, and mixing it with the class that contains the business logic, makes such class harder to maintain.
A design that might benefit you is one where you place all state changing business actions behind a common abstraction, as described here.

DDD: Referencing MediatR interface from the domain project

I'm just getting started with DDD. I'm putting domain events into a CQRS application and I'm stumbling on a fundamental task: How to use the MediatR.INotification marker interface within the domain project without creating a domain dependency on infrastructure.
My solution is organized in four projects as follows:
MyApp.Domain
- Domain events
- Aggregates
- Interfaces (IRepository, etc), etc.
MyApp.ApplicationServices
- Commands
- Command Handlers, etc.
MyApp.Infrastructure
- Repository
- Emailer, etc.
MyApp.Web
- Startup
- MediatR NuGet packages and DI here
- UI, etc.
I currently have the MediatR and MediatR .net Core DI packages installed in the UI project and they are added to DI using .AddMediatR(), with the command
services.AddMediatR(typeof(MyApp.AppServices.Commands.Command).Assembly);
which scans and registers command handlers from the AppServices project.
The problem comes when I want to define an event. For MediatR to work with my domain events, they need to be marked with the MediatR.INotification interface.
namespace ObApp.Domain.Events
{
public class NewUserAdded : INotification
{
...
}
What is the proper way to mark my events in this situation so they can be used by MediatR? I can create my own marker interface for events, but MediatR won't recognize those without some way to automatically cast them to MediatR.INotification.
Is this just a shortcoming of using multiple projects? Even if I was using a single project, though, I would be putting an "external" interface in the domain if I used MediatR.INotification from within the domain section.
I've run into the same issue when my User entity inherited from EF's IdentityUser. In that case the web consensus seems to say be pragmatic and go ahead and allow the minor pollution to save a lot of headaches. Is this another similar case? I don't mind sacrificing purity for pragmatism, but not just to be lazy.
This is a fundamental issue that will occur with other packages I use, so I look forward to solving this.
Thank you!
It is best that your domain layer doesn't depend on any infrastructure but that is hard to obtain in CQRS because of the bindings. I can tell you from my experience. You can, however, minimize that dependency. One way to do that is to make your own EventInterface that extends MediatR.INotification and use that interface all over the domain code. In this way, if you ever want to change the infrastructure, you need to change only in one place.
If you want to keep your domain layer really pure, without having any reference to MediatR, create your own interfaces for events, mediator and handler in the domain layer. Then in the infrastructure or application layer, create wrapper classes to wrap MediatR and pass the calls through the wrapper classes. With this approach, you wont need to derive from the MediatR interfaces. Make sure to register the wrappers in your IoC too
Here's an example:
in your domain layer:
public interface IDomainMediator
{
Task Publish<TNotification>(TNotification notification,
CancellationToken cancellationToken = default(CancellationToken))
where TNotification : IDomainNotification;
}
public interface IDomainNotification
{}
public interface IDomainNotificationHandler<in TNotification>
where TNotification : IDomainNotification
{
Task Handle(TNotification notification,
CancellationToken cancellationToken=default(CancellationToken));
}
Then in your infrastructure or application layer, wherever you have the MediatR package:
public class MediatRWrapper : IDomainMediator
{
private readonly MediatR.IMediator _mediator;
public MediatRWrapper(MediatR.IMediator mediator)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
}
public Task Publish<TNotification>(TNotification notification,
CancellationToken cancellationToken = default(CancellationToken))
where TNotification : IDomainNotification
{
var notification2 = new NotificationWrapper<TNotification>(notification);
return _mediator.Publish(notification2, cancellationToken);
}
}
public class NotificationWrapper<T> : MediatR.INotification
{
public T Notification { get; }
public NotificationWrapper(T notification)
{
Notification = notification;
}
}
public class NotificationHandlerWrapper<T1, T2> : MediatR.INotificationHandler<T1>
where T1 : NotificationWrapper<T2>
where T2 : IDomainNotification
{
private readonly IEnumerable<IDomainNotificationHandler<T2>> _handlers;
//the IoC should inject all domain handlers here
public NotificationHandlerWrapper(
IEnumerable<IDomainNotificationHandler<T2>> handlers)
{
_handlers = handlers ?? throw new ArgumentNullException(nameof(handlers));
}
public Task Handle(T1 notification, CancellationToken cancellationToken)
{
var handlingTasks = _handlers.Select(h =>
h.Handle(notification.Notification, cancellationToken));
return Task.WhenAll(handlingTasks);
}
}
I haven't tested it with pipelines etc, but it should work.
Cheers!
It would be first prize to attempt to first not have an infrastructure dependency in the domain layer.
I don't know MediatR but from what you describe it requires an interface to be implemented on a class that is going to be used in that space.
Is it perhaps an option to create a wrapper class that lives outside your domain?
public class MediatRNotification<T> : INotification
{
T Instance { get; }
public MediatRNotification(T instance)
{
Instance = instance;
}
}
Your infrastructure could even use some reflection to create this wrapper from a domain event.
If you want to take advantage of the mediatR polymorphism for notification without derive your domain event with MediatR.INotification, create a wrapper as told by Eben.
public class DomainEventNotification<TDomainEvent> : INotification where TDomainEvent : IDomainEvent
{
public TDomainEvent DomainEvent { get; }
public DomainEventNotification(TDomainEvent domainEvent)
{
DomainEvent = domainEvent;
}
}
Then create it with the right type instead of the domain event interface by applying dynamic. See this article for more explanation
public class DomainEventDispatcher : IDomainEventChangesConsumer
{
private readonly IMediator _mediator;
public DomainEventDispatcher(IMediator mediator)
{
_mediator = mediator;
}
public void Consume(IAggregateId aggregateId, IReadOnlyList<IDomainEvent> changes)
{
foreach (var change in changes)
{
var domainEventNotification = CreateDomainEventNotification((dynamic)change);
_mediator.Publish(domainEventNotification);
}
}
private static DomainEventNotification<TDomainEvent> CreateDomainEventNotification<TDomainEvent>(TDomainEvent domainEvent)
where TDomainEvent : IDomainEvent
{
return new DomainEventNotification<TDomainEvent>(domainEvent);
}
}
The handler of your domain event type will be called :
public class YourDomainEventHandler
: INotificationHandler<DomainEventNotification<YourDomainEvent>>
{
public Task Handle(DomainEventNotification<YourDomainEvent> notification, CancellationToken cancellationToken)
{
// Handle your domain event
}
}
public class YourDomainEvent : IDomainEvent
{
// Your domain event ...
}
this is an approach that you can use without using an infrastructure interface
https://github.com/Leanwit/dotnet-cqrs
From the GitHub site:
This project shows a clean way to use CQRS without using the MediatR
library.
In C# is common to use a library named MediatR to implement CQRS. This
is an amazing library but forces you to implement the interface
INotification, INotificationHandler and IRequestHandler in your
domain/application layer coupling this with an infrastructure library.
This is a different approach to avoid add this coupling.
As others mentioned, the consensus seems to be to wrap MediatR.INotification. I found this post from 2020 to be very useful.
We do have to deal with the small issue of our Domain Event not being a valid MediatR INotification. We’ll overcome this by creating a generic INotification to wrap our Domain Event.
Create a custom generic INotification.
using System;
using MediatR;
using DomainEventsMediatR.Domain;
namespace DomainEventsMediatR.Application
{
public class DomainEventNotification<TDomainEvent> : INotification where TDomainEvent : IDomainEvent
{
public TDomainEvent DomainEvent { get; }
public DomainEventNotification(TDomainEvent domainEvent)
{
DomainEvent = domainEvent;
}
}
}
Create a Dispatcher that wraps Domain Events in MediatR notificatoins and publishes them:
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using MediatR;
using DomainEventsMediatR.Domain;
namespace DomainEventsMediatR.Application
{
public class MediatrDomainEventDispatcher : IDomainEventDispatcher
{
private readonly IMediator _mediator;
private readonly ILogger<MediatrDomainEventDispatcher> _log;
public MediatrDomainEventDispatcher(IMediator mediator, ILogger<MediatrDomainEventDispatcher> log)
{
_mediator = mediator;
_log = log;
}
public async Task Dispatch(IDomainEvent devent)
{
var domainEventNotification = _createDomainEventNotification(devent);
_log.LogDebug("Dispatching Domain Event as MediatR notification. EventType: {eventType}", devent.GetType());
await _mediator.Publish(domainEventNotification);
}
private INotification _createDomainEventNotification(IDomainEvent domainEvent)
{
var genericDispatcherType = typeof(DomainEventNotification<>).MakeGenericType(domainEvent.GetType());
return (INotification)Activator.CreateInstance(genericDispatcherType, domainEvent);
}
}
}
Microsoft's approach
Note that in its CQRS full example, Microsoft suggests to simply reference the MediatR interface within the Domain Entity:
In C#, a domain event is simply a data-holding structure or class, like a DTO, with all the information related to what just happened in the domain, as shown in the following example:
public class OrderStartedDomainEvent : INotification
{
public string UserId { get; }
public string UserName { get; }
public int CardTypeId { get; }
public string CardNumber { get; }
public string CardSecurityNumber { get; }
public string CardHolderName { get; }
public DateTime CardExpiration { get; }
public Order Order { get; }
public OrderStartedDomainEvent(Order order, string userId, string userName,
int cardTypeId, string cardNumber,
string cardSecurityNumber, string cardHolderName,
DateTime cardExpiration)
{
Order = order;
UserId = userId;
UserName = userName;
CardTypeId = cardTypeId;
CardNumber = cardNumber;
CardSecurityNumber = cardSecurityNumber;
CardHolderName = cardHolderName;
CardExpiration = cardExpiration;
}
}
First, you add the events happening in your entities into a collection or list of events per entity. That list should be part of the entity object, or even better, part of your base entity class, as shown in the following example of the Entity base class:
public abstract class Entity
{
//...
private List<INotification> _domainEvents;
public List<INotification> DomainEvents => _domainEvents;
public void AddDomainEvent(INotification eventItem)
{
_domainEvents = _domainEvents ?? new List<INotification>();
_domainEvents.Add(eventItem);
}
public void RemoveDomainEvent(INotification eventItem)
{
_domainEvents?.Remove(eventItem);
}
//... Additional code
}

Dependency Injection Architectural Design - Service classes circular references

I have the following service classes:
public class JobService {
private UserService us;
public JobService (UserService us) {
this.us = us;
}
public void addJob(Job job) {
// needs to make a call to user service to update some user info
// similar dependency to the deleteUser method
}
}
public class UserService {
private JobService js;
public UserService(JobService js) {
this.js = js;
}
public void deleteUser(User u) {
using (TransactionScope scope = new TransactionScope()) {
List<IJob> jobs = jobService.findAllByUser(u.Id);
foreach (IJob job in jobs) {
js.deleteJob(job);
}
userDao.delete(user);
scope.Complete();
}
}
}
Each of these service classes is getting instantiated by IoC container, and there is not a functional problem, but this to me feels like there is a potential design flaw in this approach and I'm wondering if there's an alternative approach that makes more sense.
As someone already pointed out, the problem is not with limitations to the DI container but with your design.
I see the reason that you have a separate UserService and a JobService which contain a reference to each other. This is because both UserService and JobService contain some logic that needs the other service as a reference (adding a job requires adding a user, etc.). However, I think that you should NOT reference one service from the other. Rather, you should have another layer of abstraction behind the services which the services will use for the common logic. So, the services will contain the logic which can't(shouldn't) be reused and the helpers will contain the shared logic.
For example:
public class UserHelper{
//add all your common methods here
}
public class JobService {
private UserHelper us;
public JobService (UserHelper us) {
this.us = us;
}
public void addJob(Job job) {
// calls helper class
}
}
public class UserService {
public UserService(UserHelper js) {
this.js = js;
}
public void deleteUser(User u) {
// calls helper class
}
}
In this way, you won't have any issues with circular references and you will have one place which contains the logic which needs to be reused by different services.
Also, I prefer having services which are completely isolated from one another.
The problem you are having has in fact nothing to do with the limitations of your DI container, but it is a general problem. Even without any container, it will be impossible to create those types:
var job = new JobService([what goes here???]);
var user = new UserService(job);
The general answer is therefore to promote one of the dependencies to a property. This will break the dependency cycle:
var job = new JobService();
var user = new UserService(job);
// Use property injection
job.User = user;
Prevent however from using more properties than strictly needed. These dependency cycles should be pretty rare and makes it much harder to either wire your types together, or to validate the DI configuration for correctness. Constructor injection makes this much more easy.
You can decouple the services by using events. Instead of calling a dependent method of another service when an action has been performed, an event is raised. An integrator can then wire up the services through the events. A service does not even know the existence of the other service.
public class JobService
{
public event Action<User, Job> JobAdded;
public void AddJob(User user, Job job)
{
//TODO: Add job.
// Fire event
if (JobAdded != null) JobAdded(user, job);
}
internal void DeleteJobs(int userID)
{
//TODO: Delete jobs
}
}
public class UserService
{
public event Action<User> UserDeleted;
public void DeleteUser(User u)
{
//TODO: Delete User.
// Fire event
if (UserDeleted != null) UserDeleted(u);
}
public void UpdateUser(User user, Job job)
{
//TODO: Update user
}
}
The integrator wires up the services
public static class Services
{
public static JobService JobService { get; private set; }
public static UserService UserService { get; private set; }
static Services( )
{
JobService = new JobService();
UserService = new UserService();
JobService.JobAdded += JobService_JobAdded;
UserService.UserDeleted += UserService_UserDeleted;
}
private static void UserService_UserDeleted(User user)
{
JobService.DeleteJobs(user.ID);
}
private static void JobService_JobAdded(User user, Job job)
{
UserService.UpdateUser(user, job);
}
}
(Note: I simplified event raising a bit. It's not thread safe like this. But you can assume that the events are subscribed in advance and will not be changed later.)
This wont work in Autofac. See circular dependencies section of the documentation.
Constructor/Constructor Dependencies Two types with circular
constructor dependencies are not supported. You will get an exception
when you try to resolve types registered in this manner.
You could potentially use relationship types (Func<>, Lazy<>) to break the cycle.
Your code is a bit too generic to come up with a proper solution but you should consider changing the direction of dependencies regardless of what IoC container you use.
public class JobService {
private UserService us;
public JobService (UserService us) {
this.us = us;
}
public void addJob(Job job) {
// needs to make a call to user service to update some user info
}
}
public class UserService {
private JobService js;
public UserService(Func<JobService> jsFactory) {
this.js = jsFactory(this);
}
public void deleteUser(User u) {
// needs to call the job service to delete all the user's jobs
}
}
Alternatively, In the case of your example you could move deleteUser and create a method, delete all jobs on the job service and instead of refering to the user use an id. this breaks the dependency by using the id.
Another alternative is to pass the job service as a parameter to deleteUser.

Where to keep dictionaries in app using Dependency Injection

I have a legacy code, and I have a problem with reconstructor it.
At start of my application I load from WCF to property on App (this is SL application) list of users.
Then every control (for sending emails, view calendar and assigning tasks) use this property as
(App.Current as App).Users
Now, I'm trying to create Unit Test for one of controls that use this lists, and I'm stuck.
Should I make a Constructor Injection(I'm using Unity) with App as parameter? Or maybe introduce some class to hold this list?
Updated with OP's implementation as the pseudocode was incomplete.
I propose create an interface for all your application services
Inject IApplicationService to your modules.
You can use this interface for all the services the application provides(probably you will need more). Mock the interface for the unit tests
OP's implemantation
public interface IApplicationService
{
List<User> Users{get;set;}
}
public class ApplicationService : IApplicationService
{
public List<User> Users
{
get { return (App.Current as App).Users; }
set { (App.Current as App).Users = value; }
}
}
public partial class MainWindow : UserControl
{
readonly IApplicationService _applicationService
public MainWindow(IApplicationService applicationService)
{
_applicationService=applicationService;
}
}
I would create a wrapper class that will expose the list of users. In production code this class will just be a wrapper around your App.Current property and it can be injected in the constructor trough Unity.
In your Unit Tests you can easily mock the App parameter and pass it when constructing a new SUT.
Something like:
public interface IUserList
{
List<User> Users { get; }
}
public class SUT
{
private IUserList UserList { get; set; }
public SUT(IUserList userList)
{
this.UserList = userList;
}
}
public class AppUserList : IUserList
{
public List<User> Users
{
get
{
return ((App)App.Current).Users;
}
}
}
For Silverlight there is an extension model called Application Extension Services.
For infrastructure purposes that might be a better alternative than adding properties to your app class and casting App.Currentback and forth.
Downside of that model is the creation of a singleton you would have to initialize for your unit tests. It would also hide the dependency on Users in your consuming classes.
Your users seem to be just data. Making that data an ambient context which can be accessed and edited everywhere in your application will bite you. You don't know who does what with that data and when he does it. This is like a session state.
So making the dependency on your data explicit would be a first step to be able to track abuse of that data.
If it makes sense to you to create a "data holder object" that has a property for Users or directly inject that data into your consumers is up to you. If there is more data than just Usersit is tempting to put all of them into the same central data store object, even if your specific consumers don't need them.
Jimmy's answer is great, but can be provide quite a bit, and some errors fixed. Differences are explained at the bottom below the code/instructions:
Create a public interface: IUserService
public interface IUserService
{
// Implemented functionality as methods where possible for better
// extendability (like IoC)
IEnumerable<User> Users();
// Add any other user service stuff as you see fit.
void AddUser(User user);
}
Write a UserService that implements IUserService
public class UserService : IUserService
{
// If you need DI for this service, follow the same pattern of using
// fields and controller injection. I left examples in comment below.
// private readonly IRepository _repository;
// Constructor is unnecessary if you do not need DI example.
public UserService(/* IRepository repository */)
{
// _repository = repository;
}
// Methods
public IEnumerable<User> Users()
{
return ((App)App.Current).Users;
}
public void AddUser(User user)
{
((App)App.Current).Users.Add(user);
}
}
Inject IUserService into classes via their Constructor
In this case your MainWindow as an example:
public partial class MainWindow : UserControl
{
private readonly IUserService _userService;
public MainWindow(IUserService userService)
{
_userService = userService;
}
// Example method consuming the service
public IEnumerable<User> GetUsers()
{
return _userService.Users();
}
}
Differences:
Separate your User Services from a central Application Service
Better modularity. In addition I use an IApplicationService for more central/global data like Api Keys, Timeouts, cleanup, DB prepping, etc.
Return IEnumerable<T> instead of List<T>
This is just a golden rule of thumb for keeping things dry and not imposing hard instantiations on your consuming classes. Refactoring is easier/safer, and your code more extensible.
Use methods instead of properties
This is preference, but I think it smart in a service layer to use methods where possible so that you can introduce filters and overloads or continue to use dependency injection - for example, you could add GetUsers(string lastName), GetUsers(string lastName, string firstName) and maintain a clean interface for your consuming classes.
Cast App.Current without the as keyword
This is a good practice because using the as keyword means when the cast fails it will return null, rather than throw an exception. I prefer the exception because 99% of the time, if your cast fails, your next operations will too. :)
Enjoy!

How to specify the implementation you want to inject

I'm in the process of implementing a notification service. Essentially, customers can get notified in a number of ways, such as via email, text message, fax etc. Below is a rough implementation that is not wired together.
public class NotificationService
{
private readonly INotification _notification;
private readonly INotificationFormatter _formatter;
public NotificationService(
INotificationMethod notification,
INotificationFormatter formatter)
{
_notification = notification;
_formatter = formatter;
}
public void Notify(SomeParameterObject obj)
{
var formattedMessage = _formatter.Format(obj);
_notification.SendNotification(formattedMessage);
}
}
public interface INotificationFormatter
{
NotificationMessage Format(SomeParameterObject obj);
}
public interface INotification
{
void SendNotification();
}
public EmailNotification : INotification
{
public void SendNotification(NotificationMessage message)
{
// Use Exchange Web Services to send email
}
}
The NotificationService class essentially takes in a method of notification and a formatter. Obviously, each method of notification requires different formatting.
Based on business criteria, how do I select which implementation of INotification and NotificationFormatter I wish to use? Note that within the lifetime of the user using the application each notification will most likely be used. I say this because it's not as simple as instructing my container to inject implementation Foobar as it will change while the user is using the application.
I've thought of creating some sort of class that could handle pairs because it seems to makes sense to me that you wouldn't want use a text message notification formatter for a fax notification. However, I can't seem to wrap my head around a decent implementation of this.
I also own the book Dependency Injection in .NET by Mark Seemann. Did I perhaps miss something obvious?
Thank you.
How is it that you decide what kind of notification a user wants? If it can change while they're using your app, it seems like the NotificationService for that user msut be created anew for each notification you want to send them. That's ok - just use some sort of lookup to select a INotification impelmentation with an IoC container.
IoC's (I use AutoFac) let you use string-indexes to select a specific implementation. That string could come from a DB or whatever to represent the user's preference. Then you'd pass it to your IoC asking for an INotification 'decorated' with your string-choice. Upon startup, all the various implementations are registered with thier choice-strings.
I think you may be on to something with your 'pairs' comment - if INotificationFormat is closely tied to INotification and there is a possiblity of mixing them up then perhaps the INotification implementation itself should select its formatter.
What you need to do is to provide some kind of configuration infrastructure. For example, assuming that you want to keep the service just the way you've defined it, I would implement a factory returning an instance of NotificationService according to your model:
public struct NotificaitonSettings<T>
{
public Predicate<T> Predicate;
public NotificationService Service;
}
public class NotificationServiceFactory<T> : INotificationServiceFactory<T>
{
protected static List<NotificaitonSettings<T>> settings = new List<NotificaitonSettings<T>>();
static NotificationServiceFactory()
{
settings.Add(new NotificaitonSettings<T>
{
Predicate = m => !String.IsNullOrEmpty(m.Email),
Service = new NotificationService(new EmailNotification(), new EmailFormatter())
});
settings.Add(new NotificaitonSettings<T>
{
Predicate = m => !String.IsNullOrEmpty(m.Fax),
Service = new NotificationService(new FaxNotification(), new FaxFormatter())
});
}
public NotificationService Create(T model)
{
return settings.FirstOrDefault(s => s.Predicate(model)).Service;
}
}
This implementation configures the factory using static list, you could use a IoC container if it supports this kind of operations.

Categories