Separation of the logic of tutorial from the main app logic - c#

Here we are developing an email client software which has a specific UI that we need to teach that to the user.
There are some classes which handle the logic of the application. for example there is function like this in the one of main classes of project:
public void ComposeMessage(string username,string message)
{
MessageComposer.ComposeMessage(username, message);
}
so, in the above function we send a message to a user.
but in the another side of the application; there is a tutorial phase . so when user goes into tutorial side of the application , he can interact with application's buttons which we tell him , but we don't want to send real messages. so we have changed the function above like this:
public void ComposeMessage(string username,string message)
{
if(!Global.IsTutorial)
MessageComposer.ComposeMessage(username, message);
}
So there are many functions which we are adding if(!Global.IsTutorial) in their body. How can we avoid this situation? We don't want to change the body of the functions in the tutorial section and we don't want to add more codes and classes into our project. We want to keep changes low as much as possible.

There is a lot of ways to achieve what you want but all of them imply that, to start with, you don't use ComposeMessage directly but create interface for it and refactor callers to inject it as a dependency:
public interface IMessageComposer
{
void ComposeMessage(string username, string message);
}
public class MyApp
{
IMessageComposer messageComposer;
public MyApp(IMessageComposer messageComposer)
{
this.messageComposer = messageComposer;
}
public void Foo()
{
messageComposer.ComposeMessage(username, message);
}
}
When you don't rely on concrete implementation and inject dependencies you may change implementation of IMessageComposer to whatever you like without actually touching original MessageComposer's or MyApp's code.
For example you can create TutorialMessageComposer like this
public class TutorialMessageComposer : IMessageComposer
{
public void ComposeMessage(string username, string password)
{
Console.WriteLine("Tutorial mode!");
}
}
And RoutingMessageComposer decorator which will check current mode and call right composer
public class RoutingMessageComposer : IMessageComposer
{
IMessageComposer composer;
IMessageComposer tutorialComposer;
public RoutingMessageComposer(IMessageComposer composer, IMessageComposer tutorialComposer)
{
this.composer = composer;
this.tutorialComposer = tutorialComposer;
}
public void ComposeMessage(string username, string message)
{
if (Global.IsTutorial)
tutorialComposer.ComposeMessage(username, message);
else
composer.ComposeMessage(username, message);
}
}
After all preparations completed, you just need to stick RoutingMessageComposer into MyApp
var app = new MyApp(new RoutingMessageComposer(new MessageComposer(), new TutorialMessageComposer()));

Related

Provide user information from signalr request in business logic layer using autofac

I have an ASP.NET MVC 5 Application with a SignalR 2 hub and using autofac for the DI.
The entire business logic is encapsulated in manager classes in their own layer. Some manager methods need informations about the current logged in user (UserId, TenantId, ..).
I solved this problem by injecting an AuthorizationProvider into each manager class that needs the user information.
public interface IAuthorizationProvider
{
long? GetUserId();
long? GteTenantId();
}
public class MyManager : IMyManager
{
private IAuthorizationProvider _authorizationProvider;
public MyManager(IAuthorizationProvider authorizationProvider)
{
_authorizationProvider = authorizationProvider;
}
public void MyMethod()
{
// Getting the User information here is pretty simple
long userId = _authorizationProvider.GetUserId();
}
}
Normally I can get the user information from the HttpContext and from the session. So I wrote a SessionAuthorizationProvider:
public class SessionAuthorizationProvider{
public long? GetUserId()
{
HttpContext.Current?.Session?[SessionKeys.User]?.Id;
}
public long? GteTenantId() { ... }
}
But now I have a new method in the SignalR hub that use the same mechanism.
[HubName("myHub")]
public class MyHub : Hub
{
private IMyManager _myManager;
public MyHub(IMyManager myManager)
{
_myManager = myManager;
}
[HubMethodName("myHubMethod")]
public void MyHubMethod(long userId, long tenantId)
{
_myManager.MyMethod();
}
}
The problem is that a SignalR request doesn't have a session. Therefore I have also set the required user information in the hub method as parameters postet from the client.
So I thought it is the best solution for this problem to write a new AuthorizationProvider for SignalR and adapt the depdendency resolver. But I can't get the current user in the new SignalrAuthorizationProvider.
public class SignalrAuthorizationProvider{
public long? GetUserId()
{
// How to get the user information here???
}
public long? GteTenantId() { /* and here??? */ }
}
Is there a recommended solution to this problem?
Of course, I can extend MyMethod to accept the user information as a parameter. But MyMethod calls another method from another manager and that manager also calls another method. The user information is only needed for the last method call. So I had to change at least 3 methods and many more in the future.
Here is a sketch of the problem
This is a potential solution. But it's very bad
Session is not supported by SignalR by default and you should avoid using it. See No access to the Session information through SignalR Hub. Is my design is wrong?. But you still can use cookie or querystring to get the desired value.
In both case you need to have access to the HubCallerContext of the underlying hub, the one that is accessible through the Context property of the Hub.
In a ideal word you should just have to had the dependency to the SignalAuthorizationProvider
ie :
public class SignalrAuthorizationProvider {
public SignalrAuthorizationProvider(HubCallerContext context){
this._context = context;
}
private readonly HubCallerContext _context;
public long? GetUserId() {
return this._context.Request.QueryString["UserId"]
}
}
But due to SignalR design it is not possible. Context property is assigned after construction of the Hub and AFAIK there is no way to change it.
Source code here : HubDispatcher.cs
One possible solution would be to inject a mutable dependency inside the Hub and alter the object in the OnConnected, OnReconnected methods.
public class SignalrAuthorizationProvider : IAuthorizationProvider
{
private Boolean _isInitialized;
private String _userId;
public String UserId
{
get
{
if (!_isInitialized)
{
throw new Exception("SignalR hack not initialized");
}
return this._userId;
}
}
public void OnConnected(HubCallerContext context)
{
this.Initialize(context);
}
public void OnReconnected(HubCallerContext context)
{
this.Initialize(context);
}
private void Initialize(HubCallerContext context) {
this._userId = context.QueryString["UserId"];
this._isInitialized = true;
}
}
and the Hub
public abstract class CustomHub : Hub
{
public CustomHub(IAuthorizationProvider authorizationProvider)
{
this._authorizationProvider = authorizationProvider;
}
private readonly IAuthorizationProvider _authorizationProvider;
public override Task OnConnected()
{
this._authorizationProvider.OnConnected(this.Context);
return base.OnConnected();
}
public override Task OnReconnected()
{
this._authorizationProvider.OnReconnected(this.Context);
return base.OnReconnected();
}
}
Having a mutable dependency is not the best design but I can't see any other way to have access to IRequest or HubCallerContext.
Instead of having an abstract Hub class which is not a perfect solution. You can change the RegisterHubs autofac method to use AOP with Castle.Core and let the interceptor calls the methods for you.

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

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
}
}
}

C# wpf UnitTesting viewmodels

I'm trying to unit test my viewmodels in a wpf application. I have a command in my viewmodel which executes a method containing a confirmation dialog. I need to run all unit tests, so that each time opening these dialogs it requires manual confirmation.
The question I have is there any way i can programmatically know which method have confirmation dialog and programmatically click "Ok" or "Cancel"?
The best solution to this is probably not to try to click Ok or Cancel programmatically, but to prevent the creation of the dialogs while running the unit tests.
To do this, you need an abstraction for getting a user confirmation, something like this:
public interface IUserConfirmation
{
bool Confirm(string title, string message);
}
In the Execute-method of your command, you only use this abstraction instead of actually showing a dialog:
public class ViewModel
{
private void MyCommandExecuted(object parameter)
{
if (this.confirmation.Confirm("Please confirm", "Are you sure you want to ...?")
{
...
}
}
Now you create two implementations of this interface: One which actually shows a dialog to the user and another one which simply returns a preconfigured value. In your main application, you use the "real" dialog implementation and in your unit tests you use the "fake" implementation.
In order to do that, you need to be able to "inject" different implementations in your ViewModel, for example via the constructor:
public ViewModel(IUserConfirmation confirmation)
{
if (confirmation == null)
throw new ArgumentNullException("confirmation");
this.confirmation = confirmation;
}
private readonly IUserConfirmation confirmation;
This is actually a well-known pattern called "dependency injection". There are frameworks available which can help you with the creation of objects, but for simple cases like this one they're not necessary.
Here's how the two implementations could look like:
public class MessageBoxUserConfirmation : IUserConfirmation
{
public bool Confirm(string title, string message)
{
return MessageBox.Show(title, message) == true;
}
}
public class TestUserConfirmation: IUserConfirmation
{
public bool Result { get; set; }
public bool Confirm(string title, string message)
{
return this.Result;
}
}
In your unit test, you use it like this:
var confirmation = new TestConfirmation();
var viewModel = new ViewModel(confirmation);
// simulate a user clicking "Cancel"
confirmation.Result = false;
viewModel.MyCommand.Execute(...);
// verify that nothing happened
There are also frameworks for creating these fake implementations without having to write your own classes all the time, but again, for simple cases like that you probably won't need them.

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.

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