I have been reading a lot on MVC/MVP patterns.... I have a simple question....If you have a view with loads of controls....say 10 texboxes and 10 checkboxes....etc etc... Am I expected to specify the properties and events each one of them in my IView interface?....
Definitely not that way.
Your IView Interface will define set of contracts/ methods (it includes properties) that can be accessed by your business layer.
It is totally wrong to exposed your control in interface like this:
public interface IView
{
TextBox UserNameTextBox{get;set;}
}
You should not have interfaces defined in this way. This is really a bad programming.
You should rather expose some contracts that your UI layer will implement.
E.g.
public interface IView
{
public void SetUserName(string Text);
}
You can implement this interface on winform as well as webform.
Similarly, you are also not supposed to expose knowlede of UI in interface(Contract).
Lets assume a scenario where you have to display information of Employee object on UI.
You should pass Employee object to UI through this interface and UI will take care of way of representing this Employee object.
Your BL should never bother about n number of TextBoxes and checkboxes.
public class Employee
{
//first name
//last name
//is manager
//is teamleader
//address
}
public interface IEmployeeView
{
void SetEmployee(Employee employee);
}
public partial class EmployeeForm:WinForm,IEmployeeView
{
public void SetEmployee(Employee employee)
{
ENameTextBox.Text = employee.FirstName+" "+employee.LastName;
}
}
Related
Assume your model or view-model needs to display a message but it obviously doesn't want to access UI. So it implements an interface which has Notify(String) method.
Now whoever implements this interface can show the message and that object would typically be UI based class which would need to be passed to the model or view-model.
My question is, will it be frown upon to pass a UI object even though it's only being passed as interface?
I have illustrated this issue with a mock example.
public interface INotify
{
void Notify(String msg);
}
class Model
{
INotify _notify;
public Model(INotify notify )
{
_notify = notify;
}
public void Add(int a, int b)
{
int result = a + b;
_notify.Notify("The result is " + result.ToString());
}
}
class View : INotify
{
public void Notify(String msg)
{
Console.Write("I am the view, I received this: ");
Console.WriteLine(msg);
}
}
class Program
{
static void Main(string[] args)
{
View view = new View();
Model model = new Model(view);
model.Add(4, 7);
}
}
The result is as expected, the key point is that it's printed from the view.
I am the view, I received this: The result is 11
Press any key to continue . . .
In the real world, the view class would be a full blown UI class like windows form or wpf etc but it's only being passed in place for an interface that it implements. Will this be frown upon why the view is being passed as an interface that it implements?
If it will be frown upon, isn't this exactly the job of interface though? In this case, it's derived class will be expected to be some kind of UI class to show the message after all and it will have a lot of other things.
I am trying to understand the practical uses of interfaces and also solve a problem with it when occasionally model view in MVVC or MVVM might want to display a message.
The other variation is to implement full observer pattern but in my case, the model or view-model needs to display message in only in one window (never in multiple) so passing that view for interface logically makes sense.
I really don't think this would be a problem at all, as long as it doesn't affect performance in a bad way that is notable or that it looks strange later on in the project when you start to add more and more on the GUI, etc.
Is it necessary to implement interface at module level and with viewmodel in prism application?
I am not seeing any interface which could be used with multiple class.
No, view models in prism do not need to implement any interface. Not even INotifyPropertyChanged, if you don't have any data that changes from the logic-side and not from the view.
In older versions, there was IView which the views had to implement to use the ViewModelLocator, but that doesn't exist anymore.
Module definitions need to implement IModule.
EDIT after comments:
You want to create an interface for a single class if you want to be able to replace it with another class, either in production or in test.
That being said, you don't create an interface for a class, normally, but the other way round. The interface comes first and specifies what the consumer wants to do with the implementation and then one or more classes provide the implementation for one or more interfaces each.
Example:
Given the class
internal class InventoryManager
{
public IEnumerable<string> ListItems() { ... }
public void AddItem( string item ) { ... }
public void RemoveItem( string item ) { ... }
}
you don't create this interface:
public interface IInventoryManager
{
IEnumerable<string> ListItems();
void AddItem( string item );
void RemoveItem( string item );
}
but rather these two:
public interface IItemList
{
IEnumerable<string> ListItems();
}
public interface IItemStorage
{
void AddItem( string item );
void RemoveItem( string item );
}
because your interface's consumers will probably either want to look what's in the inventory or change it. And you want the option to implement a read-only inventory differently than a writeable one.
I have the following problem:
I would like to have the following objects:
Several DTOs, e. g. for employees, customers etc.
Several user controls, one (or more) for each DTO which displays the DTO content and provides modifications the user might have made back to the DTO.
The base class of these user controls provides some default functionality.
A standard button panel with CRUD operations that should work with all my user controls.
What I did so far is:
I have an abstract base class for DTOs and several special DTO classes.
I have standard functionality in my default button event handlers. As an example: The save button asks the user control for the current data (via DTO), passes data to some checking class, and if all checks passed, the data are stored in the database. To retrieve the data, there is a reference to the client object setted via constructor.
I have a base class for my user controls. This is not abstract because I would like to have designer support. Therefore, this class provides access to/from its controls via virtual methods, based on the abstract base class for DTOs.
I have a generic interface based on specific DTO types which defines data access with identical method names.
Now I create a new user control, inheriting from my user control base class and implementing the generic interface for the suited DTO class. Therefore, the BaseDTO GetData() is overridden with the new SpecialDTO GetData() method.
And here is my problem:
Within my event handler, the Client control is of my desired type, e. g. CustomerClientControl. But the invoked method is not new CustomerDTO CustomerClientControl.GetData() but the base default implementation BaseDTO BaseClientControl.GetData().
How can I get out of this? Thanks for any help or suggestions to make the whole construct a little more handsome.
Edit: Here is some code.
// in my "standard functionality"
BaseClient Client { get; } // or IClientDataAccess<BaseDTO>
void ButtonSave()
{
var data = this.Client.GetData(); // in runtime, this.Client is CustomerClient
// the following works, don't worry. :-)
if (this.CheckLogic.CheckData(data))
{
this.DataAccess.SaveData(data);
}
}
public interface IClientDataAccess<T> where T : BaseDTO
{ T GetData(); }
public BaseClient : UserControl, IClientDataAccess<BaseDTO>
{
public virtual BaseDTO GetData()
{
return new BaseDTO(); // some stupid default
}
}
public CustomerClient : BaseClient, IClientDataAccess<CustomerDTO>
{
public new CustomerDTO GetData()
{
// CustomerDTO : BaseDTO
return new CustomerDTO(this.CustomerNameTextbox);
}
}
You can't change function signature when overriding.
It means you cannot have this transform public BaseDTO GetData() -> public CustomerDTO GetData().
So you need to change CustomerClient to
public CustomerClient : BaseClient
{
public override BaseDTO GetData()
{
// CustomerDTO : BaseDTO
return new CustomerDTO(this.CustomerNameTextbox);
}
}
or to look for another class design.
I'm currently building the Data Access Layer and Business Logic Layer classes for our new application, and I have a question (obviously). First, here are some details that may help:
Using Entity Framework 5 for Model classes and data access
Each "layer" is separated in different class libraries and namespaces (i.e App.Model, App.DAL, App.BLL)
Starting with the DAL - I decided to write a base class for all DAL classes to inherit.
public abstract class DALBase<T> : IDisposable
{
protected AppEntities context;
protected DbSet set;
public DALBase()
{
context = new OECCORPEntities();
set = context.Set(typeof(T));
}
protected virtual void Save()
{
context.SaveChanges();
}
public virtual void Add(T model)
{
set.Add(model);
Save();
}
public virtual T Get(int id)
{
return (T)set.Find(id);
}
public virtual List<T> GetAll()
{
return set.OfType<T>().ToList();
}
public virtual void Delete(int id)
{
T obj = Get(id);
set.Remove(obj);
Save();
}
public virtual void Update()
{
Save();
}
public void Dispose()
{
context.Dispose();
}
}
As you will see, the base class implements a generic type which should be the type of the model the DAL class is responsible for working with. Using the generic type, in the constructor it creates a DbSet using the type of the generic argument - which is used in the predefined CRUD-like virtual functions below (add, get, etc).
And then I got the idea - wait a minute... since it's generic, I really don't have to implement DAL classes for every single model. I can just write something like this:
public class GenericDAL<T> : DALBase<T>
{
public GenericDAL() : base() {}
}
... that I can use for any of the models. OK, so on to the Business Logic Layer. I created a base class for BLL as well:
public abstract class BLLBase<T>
{
protected GenericDAL<T> dal;
public BLLBase()
{
dal = new GenericDAL<T>();
}
public virtual void Add(T model)
{
dal.Add(model);
}
public virtual T Get(int id)
{
return dal.Get(id);
}
public virtual List<T> GetAll()
{
return dal.GetAll();
}
public virtual void Delete(int id)
{
dal.Delete(id);
}
public virtual void Update()
{
dal.Update();
}
}
... which uses the GenericDAL to do its work. So in a simular fashion, I just wrote a GenericBLL class that looks like this:
public class GenericBLL<T> : BLLBase<T>
{
public GenericBLL() : base() { }
}
And to test it, a simple console application:
class Program
{
static void Main(string[] args)
{
GenericBLL<ADMIN> bll = new GenericBLL<ADMIN>();
List<ADMIN> admins = bll.GetAll();
}
}
... where "ADMIN" is the model type. Works like a charm.
The idea behind this was to avoid having to write DAL / BLL classes for every single model, unless it needed extra functionality. Can someone tell me why I WOULDN'T want to do it this way? I think the generic DAL / BLL classes would get the job done and also save development time.
Thank you for your time.
Well, one drawback is that if you decide to add some business rules later on you would have to switch the type from GenericBLL[Whatever] to WhateverBLL.
An obvious solution to this is to create a class that inherits from GenericBLL[Whatever]. Like:
public class WhateverBLL : GenericBLL<Whatever>
and use this class instead.
Right now, your BLL isn't particularly adding value. Every call is simply a pass-through to another layer. Maybe it's the simplicity of your application (and thank your lucky stars that you are so lucky), or maybe you have what I would classify as the actual business logic living elsewhere.
Business logic to me is everything that is done up to the point of persisting data, everything that is done after retrieving data, and things like that. The decisions, the forks in the road, the actions that are taken. Actually saving and retrieving data is typical extremely trivial by comparison.
So as I look at your generic DAL base class, I think it's a fine start. I would probably extract an interface from it so I could replace it when testing. For now, your class that inherits the base isn't adding any value. Do not create layers and classes simply for the sake of it, be sure it adds value and makes your life easier in some way.
As I look at your generic BLL class, I think you probably have your real business logic tucked away in the codebehind on some form, or inside a class file in a console app. While it's certainly possible that there could be generically applicable functionality that only varies on the type, I don't think one class is where you want to be. My suggestion here is to reconsider what you think is your actual business logic. A simple pass-through layer to the DAL probably isn't it.
I am using a pattern where a concrete ViewModel implementing an interface is passed to a repository, which then populates the ViewModel object, but only using the interface. This makes for a little heavier repository, but has allowed the repository to be reused in different scenarios. For example, the concrete implementation could be a MVC ViewModel, or it could be asp.net Page that implements the interface, where the set accessor for each proeprty is actually putting the value in to the GUI, like a textbox for example. The implementation of the interface serves as the mapping and eliminates an extra step of copying. Having used AutoMapper extensively, and now being exposed to this pattern, I prefer this.
public interface IPerson
{
int Id{set};
string Name{set};
string Address{set};
}
public class PersonRepository
{
GetPerson(int id, IPerson person)
{
//query...
person.Id = result.Id;
person.Name = result.Name;
person.Address = result.Address;
}
}
//...controller action
PersonViewModel person = new PersonViewModel();
rep.GetPerson(5, person);
Here comes the tricky part though. Sometimes the ViewModel needs a collection of items, either for an Index page or for something like a drop down, or to display a nested set of child objects. The repository can't instantiate an interface, so we provide it was a factory. After fighting with covariance for awhile, I gave up on exposing any type of collection and ended up with a method that both creates and adds the collection item:
public interface IPerson
{
//...
IJobRole CreateAndAddJobRole();
}
public class PersonViewModel:IPerson
{
//collection not part of the interface
ICollection<JobRoles> JobRoles {get;set;} //= new List<JobRoles> in constructor
public CreateAndAddJobRole()
{
role = new JobRole();
JobRoles.Add(role);
return role;
}
}
public class PersonRepository
{
GetPerson(int id, IPerson person)
{
//...
foreach(var result...)
{
IJobRole role = person.CreateAndAddJobRole();
role.SomeProperty = //...
}
}
}
Obviously I'd probably have the repository that handles job roles actually be the one to populate the collection. I'd probably actual have more granular interfaces so that different repositories would be responsible for populating the data they deal with. The ViewModel would simply implement multiple interfaces. That to say, I realize there's room for improvement, but I am here specifically because I don't have any good ideas for dealing with the collection problem.
The one benefit of this design is there is no collection exposed which could be misused by the repository. There is never a guess about who is responsible for instantiating the collection itself, or who populates it, or if you had just a getter, the repository could get the collection and modify it in an invalid way. I think these would be rare occurrences because of the team would know the pattern, but it's always nice to not have pitfalls at all, instead of having pitfalls there that everyone has to remember to not step in.
As it is, it feels a little mucky.
How would you design/expose the ability for concrete types to be instantiated and added to collection, when the method doing so only has knowledge of the interfaces?
It sounds like your best bet is to make each interface generic, and pass in the types of the collections. For example:
public interface IPerson<TJob> where TJob : IJobRole
{
ICollection<TJob> JobRoles {get;set;}
void AddJobRole(TJob role);
}
public JobRole : IJobRole
{
}
public class PersonViewModel:IPerson<JobRoles>
{
//collection is now part of the interface
ICollection<JobRoles> JobRoles //= new List<JobRoles> in constructor
public void AddJobRole(JobRoles role)
{
JobRoles.Add(role);
}
}
public class PersonRepository
{
GetPerson(int id, IPerson<JobRoles> person)
{
//...
foreach(var result...)
{
person.AddJobRole(new JobRole {
SomeProperty = //...
SomeOther = //...
}
}
}
}
Of course, this assumes that you know which type of IPerson<> you want when you call GetPerson(). If you need it to handle any IPerson there, though, it becomes more problematic.