I have multiple modules(each module in a different project) in my prism project. And I would like to share a same object between each module.
For example, let say I have Order class and I would like to access this Order object in my modules.
Currently, I implemented an interface and registered it with container in my Prism project.
public interface ICommonService{
Order GetData();
}
public class CommonService : ICommonService{
public Order MyOrder{ get; set; }
public Order GetData(){
return MyOrder;
}
public void SetData(Order order){
MyOrder = order;
}
}
I am using it in every module where it need MyOrder.
Is this a correct way of sharing a same object between modules?
Also, my View Models classes contains several Manager classes.
Should only View Model classes use ICommonService or can my Manager classes also use it?
I am trying to write clean and manageable code.
Thank you.
Is this a correct way of sharing a same object between modules?
Yes.
Should only View Model classes use ICommonService or can my Manager classes also use it?
The manager classes are fine to use the service.
Notes:
You should include a means of notifying other consumers of ICommonService when MyOrder changes. Examples: implement INotifyPropertyChanged or publish a MyOrderChanged event through the event aggregator
Normally, anyone who can access a service (read: knows the interface), should be allowed to do so. It's better to restrict the accessibility of the interface (by putting it in a separate assembly) than restricting accessibility of the service (by documentation), because the former is enforced by the compiler.
You can use Event Aggregation
The Prism Library provides an event mechanism that enables communications between loosely coupled components in the application. This mechanism, based on the event aggregator service, allows publishers and subscribers to communicate through events and still do not have a direct reference to each other.
Link Communicating Between Loosely Coupled Components
Prism
Sample
When you define your module, you should specify an dependencies in the constructor for that module. For example:
public class SomeModule : IModule
{
public SomeModule(ICommonService commonService)
{
// commonService will be shared object
}
}
In your Bootstrapper, when you add the module to the catalog, it will look through the DI container to look up the type. If you have it set to global reference, it will use the same object for all references to ICommonService.
class Bootstrapper : UnityBootstrapper
{
protected override void ConfigureContainer()
{
base.ConfigureContainer();
RegisterTypeIfMissing(typeof(ICommonService),
typeof(CommonService), true); // true for register as singleton
}
protected override void ConfigureModuleCatalog()
{
base.ConfigureModuleCatalog();
ModuleCatalog module_catalog = (ModuleCatalog)this.ModuleCatalog;
module_catalog.AddModule(typeof(SomeModule));
}
}
Related
I inherited a WPF/Prism/Unity MVVM application and I need to link in a Class Library that communicates externally over a serial port. The serial port library publishes Events for errors and messages.
I'm new to Prism, but I've used Unity some years back. The Prism application (lets call it PrismApp) is a base PrismApplication, with two modules: main and settings. My serial port library (lets call it LibSerial) wraps the base communications protocol and publishes three events: ConnectionEventReceived, ErrorEvent and MessageReceived. LibSerial has functions for Connect, StartSession and Send.
My questions are:
Where do I instantiate my LibSerial? Do I create a Model for it or can I instantiate LibSerial in my base PrismApplication?
How do I publish events to my ViewModels? I assume I would consume the LibSerial Events somewhere and use and EventAggregator to push various EventArgs up into the viewmodels?
How would I call my LibSerial start/startsession/send functions from within PrismApp? Would that be a DeleagateCommand in a ViewModel that calls a pubsub.publish?
Thanks Everyone!
Where do I instantiate my LibSerial?
Register it in your bootstrapper and let the container instantiate it. Override the RegisterTypes method of the PrismApplication class in your App.xaml.cs and register the LibSerial type:
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<ILibSerial, LibSerial>();
}
You can then inject your view models with an ILibSerial (which in this case is an interface that the LibSerial class implements) and hook up its events and access its members as usual:
public class ViewModel
{
public ViewModel(ILibSerial libSerial)
{
libSeriel.MessageReceived += ...;
}
}
The container will take care of the instantiation and provided that you register the type using the RegisterSingleton method in the bootstrapper, there will only be a single instance created and shared across all view models.
Background
I'm building a two-tiered C# .net application:
Tier 1: Winforms client application using the MVP (Model-View-Presenter) design pattern.
Tier 2: WebAPI RESTful service sitting on top of Entity Framework and SQL Server.
Currently, I have questions relating to the overall architecture of the Winforms client application. I'm new to programming (about a year) but I've made good progress with this application. I want to step back and re-evaluate my current approach to check that I'm generally heading in the right direction.
Application Domain
The Winforms application is a fairly simple security personnel tracking application. The main view (Form) is the focus of the application, and has different sections which group content into functional areas (e.g. a section for tracking personnel schedules, a section for tracking who is assigned where, etc.). A menu on the side of the application launches secondary views (e.g. history, statistics, contacts, etc.). The idea is that the app could be used by a security office to organize daily operations and then keep a detailed history of everything in a database for reporting on in the future.
Technical Details
As mentioned, the Winforms client is built using the MVP pattern (passive view), focusing on using dependency injection as much as possible (via SimpleInjector IoC container). Each view (form) is paired up with a single presenter. The views implement interfaces, allowing the presenter to control the view (regardless of the concrete implementation). The view raises events for the presenter to subscribe to. Currently, presenters are not allowed to directly communicate to another presenter.
An application controller is used to coordinate the application. This is the area of my application architecture where I'm the most shakey (hence the post title). The application controller is currently used to:
Open new views (forms) and manage open forms.
Facilitate communication between application components via an event aggregator. One presenter publishes an event and any number of presenter can subscribe to that event.
Host session information (i.e. security context/logon, config data, etc.)
The IoC container is registered into the application controller at application start-up. This allows the application controller, for example, to create a presenter from the container, and then have all subsequent dependencies (view, services, etc.) to be automatically handled by the container.
Question
In order to make the Application Controller accessible to all presenters, I have created the controller as a static class.
public static class ApplicationController
{
private static Session _session;
private static INavigationWorkflow _workflow;
private static EventAggregator _aggregator;
#region Registrations
public static void RegisterSession(Session session) {}
public static void RegisterWorkflow(INavigationWorkflow workflow) {}
public static void RegisterAggregator(EventAggregator aggregator) {}
#endregion
#region Properties
public static Session Session
{
get { return _session; }
}
#endregion
#region Navigation
public static void NavigateToView(Constants.View view) {}
#endregion
#region Events
public static Subscription<TMessageType> Subscribe<TMessageType>(Action<TMessageType> action) {}
public static void Publish<TMessageType>(TMessageType message) {}
public static void Unsubscribe<TMessageType>(Subscription<TMessageType> subscription) {}
#endregion
}
Is this considered an acceptable practice to make a static class like this? I mean, it certainly works. It just feels... off? Are there any other holes that you can see in my architecture based on what I have described?
-
** EDIT **
This edit is made in response to Ric .Net’s answer posted below.
I have read through all of your suggestions. As I am committed to utilizing dependency injection to the fullest extent I can, I’m onboard with all of your suggestions. That was my plan from the beginning, but when I ran into things I didn’t understand how to accomplish via injection, I turned to the global static controller class to solve my problems (A god class it is becoming, indeed. Yikes!). Some of those questions still exist:
Event Aggregator
The defining line here is what should be considered optional, I think. I’ll provide a bit more context about my app before outlining my problem. Using web terminology, my main form generally acts like a layout view, hosting navigation controls and a notification section in the left menu, and partial views being hosted in the center. Coming back to winforms terminology, the partial views are just custom made UserControls that I treat like views, and each of them are paired up with their own presenter. I have 6 of these partial views hosted on my main form, and they serve as the meat and potatoes of the application.
As an example, one partial view lists available security guards and another lists potential patrol areas. In a typical use case, a user would drag an available security guard from the available list to one of the potential patrol areas, effectively becoming assigned to that area. The patrol area view would then update to show the assigned security guard and the guard would be removed from the available list view. Utilizing drag-and-drop events, I can handle this interaction.
My questions come when I need to handle other types of interactivity between the various partial views. For example, double clicking on guard that is assigned to a location (as seen in one partial view) could highlight that guard’s name on another partial view showing all personnel schedules, or bring up employee details/history on another partial view. I could see the graph/matrix of what partial views are interested in events occurring in other partial views as becoming quite complex, and I’m not sure how to handle that via injection. With 6 partial views, I wouldn’t want to inject the other 5 partial views/presenters into each one. I was planning on accomplishing this via the event aggregator. Another example I could think of is needing to update data on a separate view (its own form) based off an event that occurs on one of the partial views on the main form.
Session & Form Opener
I really like your thoughts here. I’m going to take these ideas and run with them, and see where I end up!
Security
What are your thoughts on controlling user access to certain functionality based on what type of account they have? The recommendations I’ve been reading online say that security could be implemented by modifying the views based on their account type. The thought being, if a user can’t interact with a UI element to kick off a certain task, then the presenter will never be asked to perform that task. I’m curious if you inject the WindowsUserContext into each presenter and do additional checks, especially for http service bound requests?
I haven’t done too much development on the service side of things yet, but for http service bound requests, I imagine you need to send security information along with each request so that the service can authenticate the request. My plan was to inject the WindowsUserContext directly into the winforms service agents that end up making the service requests (i.e. the security validation would not be coming from the presenter). In that case, the service agents could potentially do a last minute security check before sending off a request.
A static class is of course handy in some cases but there are a lot of downsides to this approach.
The tend to grow into something like a God class. You already see this happening. So this class violates SRP
A static class cannot have dependencies and therefore it needs to use the Service Locator anti pattern to get it's dependencies. This is not a problem perse if you consider this class to be part of the composition root, but nevertheless, this often heads the wrong way.
In the supplied code I see three responsibilities of this class.
EventAggregator
What you call Session information
A service to open other views
Some feedback on this three parts:
EventAggregator
Although this is a widely used pattern and sometimes it can be very powerful I myself am not fond of this pattern. I see this pattern as something that provides optional runtime data where in most cases this runtime data is not optional at all. In other words, only use this pattern for truly optional data. For everything that is not really optional, use hard dependencies, using constructor injection.
The ones that need the information in that case depend upon IEventListener<TMessage>. The one that publish the event, depend upon IEventPublisher<TMessage>.
public interface IEventListener<TMessage>
{
event Action<TMessage> MessageReceived;
}
public interface IEventPublisher<TMessage>
{
void Publish(TMessage message);
}
public class EventPublisher<TMessage> : IEventPublisher<TMessage>
{
private readonly EventOrchestrator<TMessage> orchestrator;
public EventPublisher(EventOrchestrator<TMessage> orchestrator)
{
this.orchestrator = orchestrator;
}
public void Publish(TMessage message) => this.orchestrator.Publish(message);
}
public class EventListener<TMessage> : IEventListener<TMessage>
{
private readonly EventOrchestrator<TMessage> orchestrator;
public EventListener(EventOrchestrator<TMessage> orchestrator)
{
this.orchestrator = orchestrator;
}
public event Action<TMessage> MessageReceived
{
add { orchestrator.MessageReceived += value; }
remove { orchestrator.MessageReceived -= value; }
}
}
public class EventOrchestrator<TMessage>
{
public void Publish(TMessage message) => this.MessageReceived(message);
public event Action<TMessage> MessageReceived = (e) => { };
}
To be able to guarantee events are stored in one single location, we extract that storage (the event) into its own class, the EventOrchestrator.
The registration is as follows:
container.RegisterSingleton(typeof(IEventListener<>), typeof(EventListener<>));
container.RegisterSingleton(typeof(IEventPublisher<>), typeof(EventPublisher<>));
container.RegisterSingleton(typeof(EventOrchestrator<>), typeof(EventOrchestrator<>));
Usage is trivial:
public class SomeView
{
private readonly IEventPublisher<GuardChanged> eventPublisher;
public SomeView(IEventPublisher<GuardChanged> eventPublisher)
{
this.eventPublisher = eventPublisher;
}
public void GuardSelectionClick(Guard guard)
{
this.eventPublisher.Publish(new GuardChanged(guard));
}
// other code..
}
public class SomeOtherView
{
public SomeOtherView(IEventListener<GuardChanged> eventListener)
{
eventListener.MessageReceived += this.GuardChanged;
}
private void GuardChanged(GuardChanged changedGuard)
{
this.CurrentGuard = changedGuard.SelectedGuard;
}
// other code..
}
If another view will receive a lot of events you could always wrap all IEventListeners of that View in a specific EventHandlerForViewX class which get all important IEventListener<> injected.
Session
In the question you define several ambient context variables as Session information. Exposing this kind of information through a static class promotes tight coupling to this static class and thus makes it more difficult to unit test parts of your application. IMO all information provided by Session is static (in the sense that it doesn't change throughout the lifetime of the application) data that could just as easily be injected into those parts that actually need this data. So Session should completely be removed from the static class. Some examples how to solve this in a SOLID manner:
Configuration values
The composition root is in charge of reading all information from the configuration source (e.g. your app.config file). This information can there be stored in a POCO class crafted for its usage.
public interface IMailSettings
{
string MailAddress { get; }
string DefaultMailSubject { get; }
}
public interface IFtpInformation
{
int FtpPort { get; }
}
public interface IFlowerServiceInformation
{
string FlowerShopAddress { get; }
}
public class ConfigValues :
IMailSettings, IFtpInformation, IFlowerServiceInformation
{
public string MailAddress { get; set; }
public string DefaultMailSubject { get; set; }
public int FtpPort { get; set; }
public string FlowerShopAddress { get; set; }
}
// Register as
public static void RegisterConfig(this Container container)
{
var config = new ConfigValues
{
MailAddress = ConfigurationManager.AppSettings["MailAddress"],
DefaultMailSubject = ConfigurationManager.AppSettings["DefaultMailSubject"],
FtpPort = Convert.ToInt32(ConfigurationManager.AppSettings["FtpPort"]),
FlowerShopAddress = ConfigurationManager.AppSettings["FlowerShopAddress"],
};
var registration = Lifestyle.Singleton.CreateRegistration<ConfigValues>(() =>
config, container);
container.AddRegistration(typeof(IMailSettings),registration);
container.AddRegistration(typeof(IFtpInformation),registration);
container.AddRegistration(typeof(IFlowerServiceInformation),registration);
}
And where you need some specific information, e.g. information to send an email you can just put IMailSettings in the constructor of the type needing the information.
This will also give you the possibility to test a component using different config values, which would be harder to do if all config information had to come from the static ApplicationController.
For security information, e.g. the logged on User the same pattern can be used. Define an IUserContext abstraction, create a WindowsUserContext implementation and fill this with the logged on user in the composition root. Because the component now depends on IUserContext instead of getting the user at runtime from the static class, the same component could also be used in an MVC application, where you would replace the WindowsUserContext with an HttpUserContext implementation.
Opening other forms
This is actually the hard part. I normally also use some big static class with all kinds of methods to open other forms. I don't expose the IFormOpener from this answer to my other forms, because they only need to know, what to do, not which form does that task for them. So my static class exposes this kinds of methods:
public SomeReturnValue OpenCustomerForEdit(Customer customer)
{
var form = MyStaticClass.FormOpener.GetForm<EditCustomerForm>();
form.SetCustomer(customer);
var result = MyStaticClass.FormOpener.ShowModalForm(form);
return (SomeReturnValue) result;
}
However....
I'm not at all happy with this approach, because over time this class grows and grows. With WPF I use another mechanism, which I think could also be used with WinForms. This approach is based on a message based architecture described in this and this awesome blogposts. Although at first the information looks as it is not at all related, it is the message based concept that let these patterns rock!
All my WPF windows implement an open generic interface, e.g. IEditView. And if some view needs to edit a customer, it just get's this IEditView injected. A decorator is used to actually show the view in pretty much the same way as the forementioned FormOpener does it. In this case I make use of a specific Simple Injector feature, called decorate factory decorator, which you can use to create forms whenever it is needed, just as the FormOpener used the container directly to create forms whenever it needs to.
So I did not really test this, so there could be some pitfalls with WinForms, but this code seems to work on a first and single run..
public class EditViewShowerDecorator<TEntity> : IEditView<TEntity>
{
private readonly Func<IEditView<TEntity>> viewCreator;
public EditViewShowerDecorator(Func<IEditView<TEntity>> viewCreator)
{
this.viewCreator = viewCreator;
}
public void EditEntity(TEntity entity)
{
// get view from container
var view = this.viewCreator.Invoke();
// initview with information
view.EditEntity(entity);
using (var form = (Form)view)
{
// show the view
form.ShowDialog();
}
}
}
The forms and decorator should be registered as:
container.Register(typeof(IEditView<>), new[] { Assembly.GetExecutingAssembly() });
container.RegisterDecorator(typeof(IEditView<>), typeof(EditViewShowerDecorator<>),
Lifestyle.Singleton);
Security
The IUserContext must the base for all security.
For the userinterface I normally hide all controls/buttons that a certain userrole doesn't have access to. The best place is to perform this in the Load event.
Because I use the command/handler pattern as described here for my all actions external of my forms/views I use a decorator to check if a user has permission to perform this certain command (or query).
I would advise you to read this post a few times until you really get the hang of it. Once you get familiar with this pattern you won't do anything else!
If you have any questions about these patterns and how to apply a (permission)decorator, add a comment!
I apologise for the length, and I know there are some answers on this but I searched a lot and haven't found the right solution,
so please bear with me.
I am trying to create a framework for legacy applications to use DI in ASP.NET webforms. I will probably use Castle Windsor
as the framework.
These legacy applications will use in part an MVP pattern in some places.
A presenter would look something like this:
class Presenter1
{
public Presenter1(IView1 view,
IRepository<User> userRepository)
{
}
}
Now the ASP.NET Page would look something like this:
public partial class MyPage1 : System.Web.UI.Page, IView1
{
private Presenter1 _presenter;
}
Before using DI I would instantiate the Presenter as follows in the OnInit of the page:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
_presenter = new Presenter1(this, new UserRepository(new SqlDataContext()));
}
So now I want to use DI.
First I must create a handler factory to override the construction of my page.
I found THIS really good answer to help:
How to use Dependency Injection with ASP.NET Web Forms
Now I can easily set up my containers in my composition root as Mark Seeman suggest to use the Global.asax
(This means though to create a static container that must be thread safe and sealed not to be able to add further registrations)
Now I can go and declare the constructor injection on the page
public MyPage1() : base()
{
}
public MyPage1(Presenter1 presenter) : this()
{
this._presenter = presenter;
}
Now we run into the first problem, I have a circular dependency.
Presenter1 depends on IView1, But the page depends on the presenter.
I know what some will say now that the design is probably incorrect when you have circular dependencies.
First I dont think the Presenter design is incorrect, by it taking a dependency in the constructor to the View, and I can say this
by looking at plenty of MVP implementations.
Some may suggest changing the Page to a design where Presenter1 becomes a property and then using Property injection
public partial class MyPage1 : System.Web.UI.Page, IView1
{
[Dependency]
public Presenter1 Presenter
{
get; set;
}
}
Some may even suggest removing the dependency to presenter completely and then simply Wiring up via a bunch of events, But this is
not the design I wanted and frankly dont see why I need to make this change to accomodate it.
Anyway regardless of the suggestion, another problem exists:
When the Handler factory gets a page request only a type is available (NOT THE VIEW INTERFACE):
Type pageType = page.GetType().BaseType;
now using this type you can resolve the Page via IoC and its dependencies:
container.Resolve(pageType)
This will then know that there is a property called Presenter1 and be able to inject it.
But Presenter1 needs IView1, but we never resolved IView1 through the container, so the container won't know
to provide the concrete instance the handler factory just created as it was created outside of container.
So we need to hack our handler factory and replace the view interface:
So where the handler factory resolves the page:
private void InjectDependencies(object page)
{
Type pageType = page.GetType().BaseType;
// hack
foreach (var intf in pageType.GetInterfaces())
{
if (typeof(IView).IsAssignableFrom(intf))
{
_container.Bind(intf, () => page);
}
}
// injectDependencies to page...
}
This poses another problem, most containers like Castle Windsor will not allow you to reregister this interface
to the instance it is pointing to now. Also with the container being registered in the Global.asax, it is not thread-safe to
do as the container should be read only at this point.
The other solution is to create a function to rebuild the container on each web request, and then check to see
if the container contains the component IView if not set the instance. But this seems wasteful and goes against suggested use.
The other solution is to create a special Factory called
IPresenterFactory and put the dependency in the page constructor:
public MyPage1(IPresenter1Factory factory) : this()
{
this._presenter = factory.Create(this);
}
The problem is that you now need to create a factory for each presenter and then make a call to the container
to resolve other dependencies:
class Presenter1Factory : IPresenter1Factory
{
public Presenter1Factory(Container container)
{
this._container = container;
}
public Presenter1 Create(IView1 view)
{
return new Presenter1(view, _container.Resolve<IUserRepository>,...)
}
}
This design also seems cumbersome and over complicated, does any one have ideas for a more elegant solution?
Perhaps I misunderstand your problems, but the solution seems fairly simple to me: promote the IView to a property on the Presenter1:
class Presenter1
{
public Presenter1(IRepository<User> userRepository)
{
}
public IView1 View { get; set; }
}
This way you can set the presenter on the view like this:
public Presenter1 Presenter { get; set; }
public MyPage1()
{
ObjectFactory.BuildUp(this);
this.Presenter.View = this;
}
Or without property injection, you can do it as follows:
private Presenter1 _presenter;
public MyPage1()
{
this._presenter = ObjectFactory.Resolve<Presenter1>();
this._presenter.View = this;
}
Constructor injection in Page classes and user controls will never really work. You can get it to work in full trust (as this article shows), but it will fail in partial trust. So you will have to call the container for this.
All DI containers are thread-safe, as long as you don't manually add registrations yourself after the initialization phase and with some containers even that is thread-safe (some containers even forbid registering types after initialization). There would never be a need to do this (except for unregistered type resolution, which most containers support). With Castle however, you need to register all concrete types upfront, which means it needs to know about your Presenter1, before you resolve it. Either register this, change this behavior, or move to a container that allows resolving concrete types by default.
I have created a win form solution in C#. The solution has three projects, front layer (FL) business layer (BL) and data layer (DL).
Front layer has all forms. All of the forms implement IForms interface
Business layer has all business logic. All of the business logic classes implement IController interface
Data layer has all data logic that communicates with the sql database. All of the data logic classes inherit IModel interface
I am trying to use MVC design pattern but I am struggling a bit.
Target: Call a method in a class of BL, when I press a button in a form.
If I add BL dll to FL, then I can call the methods of BL.
BL.Class classObject = new BL.Class(this);
classObject.CallMethod();
In the BL, I want to have the reference of the object that called the method so I tried to add reference of the FL dll but it says Circular dll reference.
I want to have a constructor in the BL class:
public BL.Class(IView view)
{
MessageBox(view.Name);
}
How do I architect my solution to achieve this? Please note that the solution is big so I cannot merge all classes into one dll.
Take care,
FM
You are trying to inject presentation logic into your business layer. Your BL should not be creating message boxes - that is the reponsibility of the presentation layer.
You can define events in BL for FL to register. Whenever there's a change in the model, BL should fire an event. It's up for the view to handle it.
Your BL is created a message box. What if your view is a WebForm? BL shouldn't know the detail of view.
Also, your BL project shouldn't have a dll reference to FL. You need to declare IView in BL, not FL.
EDIT:
This is the structure I used before. Your BL defines the interface. Your view has to implement the interface if it wants to use the BL. BL uses the interface to interact with the view. This way, you can build different views that use the same BL.
BL.dll
public interface IView
{
/// <summary>Update the view</summary>
void UpdateView(object myBusinessObject);
/// <summary>Display message</summary>
void ShowMessage(string msg);
}
public class BL
{
// Model and View
private IView _view;
/// <summary>Constructor</summary>
public BL (IView view)
{
_view = view;
}
public void foo()
{
// Do something
// Show message
_view.ShowMessage("Hello World");
}
}
FL.dll
public class FL
{
private BL _myBL;
/// <summary>Constructor</summary>
public FL ()
{
_myBL = new BL(this);
}
/// <summary>Handles user event</summary>
public void handleEvent()
{
// Call BL to do something
_myBL.foo();
}
public void UpdateView(object myBusinessObject)
{
// Update your view
}
public void ShowMessage(string msg)
{
// Display message to user
}
}
I know your programming winforms but you might like to have a look at the WebFormsMVP or MVVM patterns to get some idea's.
"In the BL, I want to have the reference of the object that called the method so I tried to add reference of the FL dll but it says Circular dll reference."
Specifically in the WebFormsMVP project, arguments are passed between between layers based on the way they are in the .Net framework eg (object sender, mySpecialEventArgs e) - the second argument in the parameter "mySpecialEventArgs" has all the info to pass to and fro.
The basic idea behind layered architecture is nth layer should talk to n+1th layer but never cross a layer in between so nth layer cannot jump and directly talk to n+2th layer.
this was a architecture Principle, now coming down to your case.
1- 1st you are talking about the 3 layered architecture , it's not the 3 tier architecture because you are not hosting your DAL OR BL in sepreate server but you are creating individual layers in your solution ( by creating seperate project)
2- As you have three DLLS (FL, BL ,DAL) so now your layering must be FL -- > BL----> DAL where ---> represents talked to.
How you will attain above path (FL -- > BL----> DAL) in your application?
For this , you can add reference of DAL in the BL project and BL reference to your FL project , in this way you can adhere to the architectural Principle stated above.
How to implement MVC in your case?
1- 'C' stands for Controller in the MVC , Controller is a class which is responsible for updating FL and Your Model. So youneed to create a individual unique controller for individual unique functionality in your application ( please note , you don't need to create a controller for each form in your application) so if you have Order Module than create OrderBaseController and pass this controller as a reference to your views (Winform)
2- Controller created in the step 1 can expose model (remember , we have the reference of BL in our FL) which can be consumed by the OrderView.
3- View can change the model through controller( note model is in BL but we have the reference in our FL) but actual database changes still not commited.
How will you do the step 3 above?
interface IOrderController
{
bool SaveOrder(order order);
bool ValidateOrder(order order);
order GetOrder();
}
public class OrderBaseController : IOrderController
{
private OrderServiceFacade Orderhelper { get; set; }
public OrderBaseController()
{
Orderhelper = new OrderServiceFacade();
}
public bool ValidateOrder(order objOrder)
{
}
#region IOrderController Members
public bool SaveOrder(order order)
{
bool success = false;
if (ValidateOrder(order))
{
success = Orderhelper.SaveOrder(order);
}
return success;
}
#endregion
#region IOrderController Members
public order GetOrder()
{
throw new NotImplementedException();
}
#endregion
}
we have just implemented a ordercontroller.Now its time to attach this controller to the view.
public partial class Form1 : Form
{
IOrderController Controller;
public order OrderToBeSaved { get; set; }
public Form1()
{
InitializeComponent();
Controller = new OrderBaseController(); // you have the controller ,
// controller creation can also be delegated to some other component but that's totally different issue.
OrderToBeSaved = Controller.GetOrder(); // You got the order object here , once you get the order object you can bind its properties to the different control.
}
}
you got the fully loaded order object, you can use it's properties to bind the different control on the form.
now it's time to save the order
private void btnSave_Click(object sender, EventArgs e)
{
Controller.SaveOrder(OrderToBeSaved);
}
here we have deleagted saving logic to the controller , now let's see how to save the from the controller. Befor Controller save the order , it has to go through the chain i.e. it must have some logic to talk to the BL (Controller is in FL)
Since we have the reference of BL in our FL , we can directly talk to BL but we go through one more design concept which we call ServiceFacade , A ServiceFacade a class which will be used to delegate the task from one layer to another layer.
class OrderServiceFacade
{
public bool SaveOrder(order order)
{
return OrderDAO.SaveOrder(order);
}
}
Finally we need to save the order in the database so we need to define a class in our DAL we call it OrderDAO.
static class OrderDAO
{
static public bool SaveOrder(order order)
{
// put logic to access database and save the data.
}
static DataTable GetOrder(int OrderID);
}
it is not complete but it gives you the idea how MVC works in a layered scenarion.
There are actually suggested designs for this type of thing. Most of the documentation on this is specifically directed at WPF which you will find if you look up MVVM (another name for MVC).
Basically, you will need a fourth dll which is kind of a framework layer. This is what you will need:
a ServiceProvider class - something that implements IServiceProvider.
Why do we need this? Because your FL is going to provide UI services. In your case a MessageBox service. However, you may discover this is so useful, you will want to create other services. Like something to browse for a file or folder. There's more but we'll stick with this for now.
Your ServiceProvider class should also keep a list of the services it knows about, and provide a way to add to this list. A full service provider would probably include the following.
private readonly Dictionary<Type,object> mServices = new Dictionary<Type,object>();
public void Add(Type type,object value) { ...}
public object GetService(Type serviceType) { ... }
public void Remove(Type type) { ... }
public T Resolve<T>() { return (T)this.GetService(typeof(T)); }
If you make it a singleton class, then you can use this service provide anywhere.
The next job is to create services. In your new framework dll create an interface like IMessageBoxService with a bunch of methods that you might want to call to trigger message to the user. You can start simple with just a function like the following, and add as necessary later.
void ShowError(string message);
You will then need to implement this interface in your FL dll. This implementation will do the actual calls to MessageBox.
The next step is to register your new service implementation with the service provider. So somewhere before the GUI opens call the ServiceProvider.add(typeof(IMessageBoxService), new MyMessageBoxService());
Now in your business logic every time you need to popup a message you can ask the service provider for the message box service, and call the method you want in the IMessageBoxService. Something like this...
IMessageBoxService wMess = ServiceProvider.GetInstance().Resolve<IMessageBoxService>();
wMess.ShowError("My Error Message");
Now you have a clean and beautiful MVC compliant design for popping up error messages without any nasty circular dependencies.
If you want to see more about MVVM and what it is all about you can check out the Microsoft link. Or there is a full MVVM framework that someone has taken the trouble to create for WPF that has a lot of interesting features. If you have time you might want to look at that as well.
Microsoft Introduces MVVM
MVVM Framework
Why BL needs to know about FL? A real BL is independent of FL, At the moment FL is being implemented using WindowsForms, if later the FL was needed to be changed to WPF then, BL needs to change as well. Then what was layered if change in one layer effects the other layer as well? The idea of BL is that it is independent of presentation layer but can be used by different FL. BL should not make any assumption or need to know about FL.
You won't be able to have both layers know about each other if they're implemented as separate projects (causes circular dependencies).
One way to do it would be to use the observer pattern. Setup events in the business classes, and have the presentation layer subscribe to those events. When the business layer completes its actions, it can trigger the events and pass the results back to the view. The business class don't need to know about the presentation layer, it just knows that there are objects subscribed to it, and avoids creating circular dependencies.
Update: Here's one way to have the BL call the FL using events. It's kind of circular logic, but if you've already structured your code around the 2 layers knowing about each other, then you can consider this.
class BL
{
public void CallFromFL (int parameter)
{
int result = DoSomeWork (parameter);
if (OnComplete != null)
OnComplete (result);
}
public event Action <int> OnComplete;
}
class FL
{
void Foo ()
{
BL bl = new BL ();
bl.OnComplete += this.getResult;
bl.CallFromFL (5);
}
void GetResult (int result) {...}
}
I'm experimenting with MVVM for the first time and really like the separation of responsibilities. Of course any design pattern only solves many problems - not all. So I'm trying to figure out where to store application state and where to store application wide commands.
Lets say my application connects to a specific URL. I have a ConnectionWindow and a ConnectionViewModel that support gathering this information from the user and invoking commands to connect to the address. The next time the application starts, I want to reconnect to this same address without prompting the user.
My solution so far is to create an ApplicationViewModel that provides a command to connect to a specific address and to save that address to some persistent storage (where it's actually saved is irrelevant for this question). Below is an abbreviated class model.
The application view model:
public class ApplicationViewModel : INotifyPropertyChanged
{
public Uri Address{ get; set; }
public void ConnectTo( Uri address )
{
// Connect to the address
// Save the addres in persistent storage for later re-use
Address = address;
}
...
}
The connection view model:
public class ConnectionViewModel : INotifyPropertyChanged
{
private ApplicationViewModel _appModel;
public ConnectionViewModel( ApplicationViewModel model )
{
_appModel = model;
}
public ICommand ConnectCmd
{
get
{
if( _connectCmd == null )
{
_connectCmd = new LambdaCommand(
p => _appModel.ConnectTo( Address ),
p => Address != null
);
}
return _connectCmd;
}
}
public Uri Address{ get; set; }
...
}
So the question is this: Is an ApplicationViewModel the right way to handle this? How else might you store application state?
EDIT: I'd like to know also how this affects testability. One of the primary reasons for using MVVM is the ability to test the models without a host application. Specifically I'm interested in insight on how centralized app settings affect testability and the ability to mock out the dependent models.
I generally get a bad feeling about code that has one view model directly communicating with another. I like the idea that the VVM part of the pattern should be basically pluggable and nothing inside that area of the code should depend of the existence of anything else within that section. The reasoning behind this is that without centralising the logic it can become difficult to define responsibility.
On the other hand, based on your actual code, it may just be that the ApplicationViewModel is badly named, it doesn't make a model accessible to a view, so this may simply be a poor choice of name.
Either way, the solution comes down to a break down of responsibility. The way I see it you have three things to achieve:
Allow the user to request to connect to an address
Use that address to connect to a server
Persist that address.
I'd suggest that you need three classes instead of your two.
public class ServiceProvider
{
public void Connect(Uri address)
{
//connect to the server
}
}
public class SettingsProvider
{
public void SaveAddress(Uri address)
{
//Persist address
}
public Uri LoadAddress()
{
//Get address from storage
}
}
public class ConnectionViewModel
{
private ServiceProvider serviceProvider;
public ConnectionViewModel(ServiceProvider provider)
{
this.serviceProvider = serviceProvider;
}
public void ExecuteConnectCommand()
{
serviceProvider.Connect(Address);
}
}
The next thing to decide is how the address gets to the SettingsProvider. You could pass it in from the ConnectionViewModel as you do currently, but I'm not keen on that because it increases the coupling of the view model and it isn't the responsibility of the ViewModel to know that it needs persisting. Another option is to make the call from the ServiceProvider, but it doesn't really feel to me like it should be the ServiceProvider's responsibility either. In fact it doesn't feel like anyone's responsibility other than the SettingsProvider. Which leads me to believe that the setting provider should listen out for changes to the connected address and persist them without intervention. In other words an event:
public class ServiceProvider
{
public event EventHandler<ConnectedEventArgs> Connected;
public void Connect(Uri address)
{
//connect to the server
if (Connected != null)
{
Connected(this, new ConnectedEventArgs(address));
}
}
}
public class SettingsProvider
{
public SettingsProvider(ServiceProvider serviceProvider)
{
serviceProvider.Connected += serviceProvider_Connected;
}
protected virtual void serviceProvider_Connected(object sender, ConnectedEventArgs e)
{
SaveAddress(e.Address);
}
public void SaveAddress(Uri address)
{
//Persist address
}
public Uri LoadAddress()
{
//Get address from storage
}
}
This introduces tight coupling between the ServiceProvider and the SettingsProvider, which you want to avoid if possible and I'd use an EventAggregator here, which I've discussed in an answer to this question
To address the issues of testability, you now have a very defined expectancy for what each method will do. The ConnectionViewModel will call connect, The ServiceProvider will connect and the SettingsProvider will persist. To test the ConnectionViewModel you probably want to convert the coupling to the ServiceProvider from a class to an interface:
public class ServiceProvider : IServiceProvider
{
...
}
public class ConnectionViewModel
{
private IServiceProvider serviceProvider;
public ConnectionViewModel(IServiceProvider provider)
{
this.serviceProvider = serviceProvider;
}
...
}
Then you can use a mocking framework to introduce a mocked IServiceProvider that you can check to ensure that the connect method was called with the expected parameters.
Testing the other two classes is more challenging since they will rely on having a real server and real persistent storage device. You can add more layers of indirection to delay this (for example a PersistenceProvider that the SettingsProvider uses) but eventually you leave the world of unit testing and enter integration testing. Generally when I code with the patterns above the models and view models can get good unit test coverage, but the providers require more complicated testing methodologies.
Of course, once you are using a EventAggregator to break coupling and IOC to facilitate testing it is probably worth looking into one of the dependency injection frameworks such as Microsoft's Prism, but even if you are too late along in development to re-architect a lot of the rules and patterns can be applied to existing code in a simpler way.
If you weren't using M-V-VM, the solution is simple: you put this data and functionality in your Application derived type. Application.Current then gives you access to it. The problem here, as you're aware, is that Application.Current causes problems when unit testing the ViewModel. That's what needs to be fixed. The first step is to decouple ourselves from a concrete Application instance. Do this by defining an interface and implementing it on your concrete Application type.
public interface IApplication
{
Uri Address{ get; set; }
void ConnectTo(Uri address);
}
public class App : Application, IApplication
{
// code removed for brevity
}
Now the next step is to eliminate the call to Application.Current within the ViewModel by using Inversion of Control or Service Locator.
public class ConnectionViewModel : INotifyPropertyChanged
{
public ConnectionViewModel(IApplication application)
{
//...
}
//...
}
All of the "global" functionality is now provided through a mockable service interface, IApplication. You're still left with how to construct the ViewModel with the correct service instance, but it sounds like you're already handling that? If you're looking for a solution there, Onyx (disclaimer, I'm the author) can provide a solution there. Your Application would subscribe to the View.Created event and add itself as a service and the framework would deal with the rest.
Yes, you are on the right track. When you have two controls in your system that need to communicate data, you want to do it in a way that is as decoupled as possible. There are several ways to do this.
In Prism 2, they have an area that is kind of like a "data bus". One control might produce data with a key that is added to the bus, and any control that wants that data can register a callback when that data changes.
Personally, I have implemented something I call "ApplicationState". It has the same purpose. It implements INotifyPropertyChanged, and anyone in the system can write to the specific properties or subscribe for change events. It is less generic than the Prism solution, but it works. This is pretty much what you created.
But now, you have the problem of how to pass around the application state. The old school way to do this is to make it a Singleton. I am not a big fan of this. Instead, I have an interface defined as:
public interface IApplicationStateConsumer
{
public void ConsumeApplicationState(ApplicationState appState);
}
Any visual component in the tree may implement this interface, and simply pass the Application state to the ViewModel.
Then, in the root window, when the Loaded event is fired, I traverse the visual tree and look for controls that want the app state (IApplicationStateConsumer). I hand them the appState, and my system is initialized. It is a poor-man's dependency injection.
On the other hand, Prism solves all of these problems. I kind of wish I could go back and re-architect using Prism... but it is a bit too late for me to be cost-effective.