Mapping back Viewmodels to Models - c#

In my N-Layered DDD architectured, all my ViewModel classes in application layer, implement following interface:
public interface IViewModel
{
ModelEntitySuperType ToModel();
}
So each ViewModel knows how to map back to the Domain Object(by implementing the ToModel() method).
[Updated]
Also I used CQRS pattern in my Application layer, so I defined the following generic abstract class for implementing Update command, you can see the usage of ToModel() method in followiing class(Handle method):
public abstract class UpdateCommandHandler<TCommandParameter, TViewModel, TEntity> : ICommandHandler<TCommandParameter>
where TCommandParameter : UpdateCommandParameter<TViewModel>
where TViewModel : class, IViewModel, new()
where TEntity : ModelEntitySuperType, IAggregateRoot, new()
{
private readonly IRepository<TEntity> _repository;
public string Code { get; set; }
protected UpdateCommandHandler(IRepository<TEntity> repository, string commandCode)
{
Code = commandCode;
_repository = repository;
}
public void Handle(TCommandParameter commandParameter)
{
var viewModel = commandParameter.ViewModelEntity;
var entity = viewModel.ToModel() as TEntity;
_repository.Update(entity);
}
}
Is it a correct way, that I put mapping logic into ViewModel objects?
What is better way to achieve this goal?

Usually I have mapping logic in layer which does mapping. Thus I keep both entities and view models unaware of each other and they have single responsibility. Responsibility of mapping between data types goes to mapping library (e.g. AutoMapper) or to extension methods.
E.g. if you want to convert Person entity to PersonViewModel, then with AutoMapper it will look like
var viewModel = Mapper.Map<PersonViewModel>(person);
Or you can have extension method
public static PersonViewModel ToViewModel(this Person person)
{
// create view model and map its properties manually
}
Usage will look like your current code, except you don't need to cast ModelEntitySuperType to PersonViewModel:
var viewModel = person.ToViewModel();

Related

Reusing a View on MVVM pattern with EFCore

I'm working with EF Core and MVVM pattern, and I'm not sure how to proceed on how to create a "reusable" view.
I have a view with a menu strip with common operations (CRUD and filtering) and a DataGrid that would be filled via EF Core. I have a bunch of different models (all of which inherit a simple base model class with a single int ID property), and I need to display my data.
Now, according to DRY, since the views are practically identical, I shouldn't create a different view for each model, just create a generic view and fill it accordingly. Also, I've read here that viewmodels aren't usually reusable, so I would need one viewmodel for each model. And here's my question.
When creating my view, I was taught this pattern:
public class StockView : Window
{
private StockViewModel _viewModel;
public StockView(StockViewModel viewModel)
{
InitializeComponent();
_viewModel = viewModel ?? new StockViewModel();
DataContext = _viewModel;
}
}
However, that would mean this view would only accept StockViewModel, so I wouldn't be able to reuse it. I've tried creating an abstract viewmodel base for all viewmodels to inherit from, and created my generic view as
public class GenericView : Window
{
private ViewModelBase _viewModel;
public GenericView(ViewModelBase viewModel)
{
InitializeComponent();
_viewModel = viewModel ?? new ViewModelBase();
DataContext = _viewModel;
}
}
But now, I won't be able to access any of the viewmodel methods that would fetch me data asynchronously. Async abstract methods aren't allowed, and I tried creating a method that would a service class that would return me my data, but I can't use it either:
public class StockService
{
private MyDbContext _context = new MyDbContextFactory().CreateContext();
public async Task<List<Stock>>GetStocksAsync()
{
return await _context.STOCKs.Select(x=>x).ToListAsync();
}
}
public abstract class ViewModelBase
{
public abstract List<EntityBase> GetAllData();
}
public class StockViewModel : ViewModelBase
{
public override List<EntityBase> GetAll()
{
var stockServ= new StockService();
return stockServ.GetStocksAsync().Result; //<==== this doesn't compile as the method expect List<EntityBase> but it returns List<Stock>
}
}
How would I be able to reuse a view for different viewmodels, then?
Async abstract methods aren't allowed ...
No, but async is an implementation detail. An abstact class or an interface may still define a method that returns a Task<T> that you can then implement asynchronously:
public abstract class BaseViewModel<T>
{
public abstract Task<IEnumerable<T>> GetItems();
}
public class StockViewModel : BaseViewModel<Stock>
{
public override async Task<IEnumerable<Stock>> GetItems()
{
await ...
return ...
}
}

C# Downcasting with generics

In our project we are using .net WPF with MEF and prism.
I have to do some task and as a part of it I have different classes of Model, all implementing IModel interface (let's call them Model1, Model2, Model3).
For each model class I need to create a view model (ViewModel1, ViewModel2, ViewModel3).
I would like to do it in some generic way so it will be extensible and if tomorrow someone will implement IModel in different dll that I doesn't know about, I still will be able to create a view model for it.
I though about something like this:
[InheritedExport]
public interface IViewModelFactory<T>
{
IViewModel Create(string id, IEnumerable<IModel> modelsList);
}
public class ViewModelFactory : IViewModelFactory<Model1>
{
public IViewModel Create(string id, IEnumerable<IModel> modelsList)
{
return new ViewModel1(targetId, modelsList);;
}
}
public class FactoryLocator
{
public static IViewModelFactory<T> GetFactory<T>(T parameters)
{
return ServiceLocator.Current.GetInstance<IViewModelFactory<T>>();
}
}
And then I will use it that way:
public void CreateAndAddVM(IList<IModel> modelsList)
{
var factory = FactoryLocator.GetFactory(modelsList.FirstOrDefault());
var vm = factory.Create(_id, modelsList);
ViewModels.Add(vm);
}
When I get to the FactoryLocator, the type is actually IModel interface and not a Model1/2/3.
Is there any way to make it work somehow? Or maybe another way to implement this requirement?
You should start with interface defined like this
public interface IViewModelFactory<T> where T : IModel
{
IViewModel Create(string id, IEnumerable<T> modelsList);
}
and it will actually force correct typing on future implementers.
As I mentioned in my comment. At this moment, anyone can create a view model with a model that may not be intended for it.
For example, if your ViewModel depends on Model1, there's nothing stopping me from providing a list of Model2 to the Create method in your factory.
Consider the following:
public abstract class ViewModelBase<TModel> where TModel : IModel
The example above will allow your ViewModel to specify what Model it represents, however this goes by the assumption that a ViewModel only has one Model, which may not always be the case.
In this scenario, your ViewModelBase class should have an ID, and a Model property for the TModel.
Ensure that IModel inherits from INotifyPropertyChanged, this will allow TModel to be an ObservableCollection.

Using the Generic repository/Unit of work pattern in large projects

I'm working on a quite large application. The domain has about 20-30 types, implemented as ORM classes (for example EF Code First or XPO, doesn't matter for the question). I've read several articles and suggestions about a generic implementation of the repository pattern and combining it with the unit of work pattern, resulting a code something like this:
public interface IRepository<T> {
IQueryable<T> AsQueryable();
IEnumerable<T> GetAll(Expression<Func<T, bool>> filter);
T GetByID(int id);
T Create();
void Save(T);
void Delete(T);
}
public interface IMyUnitOfWork : IDisposable {
void CommitChanges();
void DropChanges();
IRepository<Product> Products { get; }
IRepository<Customer> Customers { get; }
}
Is this pattern suitable for really large applications? Every example has about 2, maximum 3 repositories in the unit of work. As far as I understood the pattern, at the end of the day the number of repository references (lazy initialized in the implementation) equal (or nearly equal) to the number of domain entity classes, so that one can use the unit of work for complex business logic implementation. So for example let's extend the above code like this:
public interface IMyUnitOfWork : IDisposable {
...
IRepository<Customer> Customers { get; }
IRepository<Product> Products { get; }
IRepository<Orders> Orders { get; }
IRepository<ProductCategory> ProductCategories { get; }
IRepository<Tag> Tags { get; }
IRepository<CustomerStatistics> CustomerStatistics { get; }
IRepository<User> Users { get; }
IRepository<UserGroup> UserGroups { get; }
IRepository<Event> Events { get; }
...
}
How many repositories cab be referenced until one thinks about code smell? Or is it totally normal for this pattern? I could probably separate this interface into 2 or 3 different interfaces all implementing IUnitOfWork, but then the usage would be less comfortable.
UPDATE
I've checked a basically nice solution here recommended by #qujck. My problem with the dynamic repository registration and "dictionary based" approach is that I would like to enjoy the direct references to my repositories, because some of the repositories will have special behaviour. So when I write my business code I would like to be able to use it like this for example:
using (var uow = new MyUnitOfWork()) {
var allowedUsers = uow.Users.GetUsersInRolw("myRole");
// ... or
var clothes = uow.Products.GetInCategories("scarf", "hat", "trousers");
}
So here I'm benefiting that I have a strongly typed IRepository and IRepository reference, hence I can use the special methods (implemented as extension methods or by inheriting from the base interface). If I use a dynamic repository registration and retrieval method, I think I'm gonna loose this, or at least have to do some ugly castings all the time.
For the matter of DI, I would try to inject a repository factory to my real unit of work, so it can lazily instantiate the repositories.
Building on my comments above and on top of the answer here.
With a slightly modified unit of work abstraction
public interface IMyUnitOfWork
{
void CommitChanges();
void DropChanges();
IRepository<T> Repository<T>();
}
You can expose named repositories and specific repository methods with extension methods
public static class MyRepositories
{
public static IRepository<User> Users(this IMyUnitOfWork uow)
{
return uow.Repository<User>();
}
public static IRepository<Product> Products(this IMyUnitOfWork uow)
{
return uow.Repository<Product>();
}
public static IEnumerable<User> GetUsersInRole(
this IRepository<User> users, string role)
{
return users.AsQueryable().Where(x => true).ToList();
}
public static IEnumerable<Product> GetInCategories(
this IRepository<Product> products, params string[] categories)
{
return products.AsQueryable().Where(x => true).ToList();
}
}
That provide access the data as required
using(var uow = new MyUnitOfWork())
{
var allowedUsers = uow.Users().GetUsersInRole("myRole");
var result = uow.Products().GetInCategories("scarf", "hat", "trousers");
}
The way I tend to approach this is to move the type constraint from the repository class to the methods inside it. That means that instead of this:
public interface IMyUnitOfWork : IDisposable
{
IRepository<Customer> Customers { get; }
IRepository<Product> Products { get; }
IRepository<Orders> Orders { get; }
...
}
I have something like this:
public interface IMyUnitOfWork : IDisposable
{
Get<T>(/* some kind of filter expression in T */);
Add<T>(T);
Update<T>(T);
Delete<T>(/* some kind of filter expression in T */);
...
}
The main benefit of this is that you only need one data access object on your unit of work. The downside is that you don't have type-specific methods like Products.GetInCategories() any more. This can be problematic, so my solution to this is usually one of two things.
Separation of concerns
First, you can rethink where the separation between "data access" and "business logic" lies, so that you have a logic-layer class ProductService that has a method GetInCategory() that can do this:
using (var uow = new MyUnitOfWork())
{
var productsInCategory = GetAll<Product>(p => ["scarf", "hat", "trousers"].Contains(u.Category));
}
Your data access and business logic code is still separate.
Encapsulation of queries
Alternatively, you can implement a specification pattern, so you can have a namespace MyProject.Specifications in which there is a base class Specification<T> that has a filter expression somewhere internally, so that you can pass it to the unit of work object and that UoW can use the filter expression. This lets you have derived specifications, which you can pass around, and now you can write this:
using (var uow = new MyUnitOfWork())
{
var searchCategories = new Specifications.Products.GetInCategories("scarf", "hat", "trousers");
var productsInCategories = GetAll<Product>(searchCategories);
}
If you want a central place to keep commonly-used logic like "get user by role" or "get products in category", then instead of keeping it in your repository (which should be pure data access, strictly speaking) then you could have those extension methods on the objects themselves instead. For example, Product could have a method or an extension method InCategory(string) that returns a Specification<Product> or even just a filter such as Expression<Func<Product, bool>>, allowing you to write the query like this:
using (var uow = new MyUnitOfWork())
{
var productsInCategory = GetAll(Product.InCategories("scarf", "hat", "trousers");
}
(Note that this is still a generic method, but type inference will take care of it for you.)
This keeps all the query logic on the object being queried (or on an extensions class for that object), which still keeps your data and logic code nicely separated by class and by file, whilst allowing you to share it as you have been sharing your IRepository<T> extensions previously.
Example
To give a more specific example, I'm using this pattern with EF. I didn't bother with specifications; I just have service classes in the logic layer that use a single unit of work for each logical operation ("add a new user", "get a category of products", "save changes to a product" etc). The core of it looks like this (implementations omitted for brevity and because they're pretty trivial):
public class EFUnitOfWork: IUnitOfWork
{
private DbContext _db;
public EntityFrameworkSourceAdapter(DbContext context) {...}
public void Add<T>(T item) where T : class, new() {...}
public void AddAll<T>(IEnumerable<T> items) where T : class, new() {...}
public T Get<T>(Expression<Func<T, bool>> filter) where T : class, new() {...}
public IQueryable<T> GetAll<T>(Expression<Func<T, bool>> filter = null) where T : class, new() {...}
public void Update<T>(T item) where T : class, new() {...}
public void Remove<T>(Expression<Func<T, bool>> filter) where T : class, new() {...}
public void Commit() {...}
public void Dispose() {...}
}
Most of those methods use _db.Set<T>() to get the relevant DbSet, and then just query it with LINQ using the provided Expression<Func<T, bool>>.

C# derivative generic type arguments

I am making a web application using ASP.NET MVC 4, Entity Framework and C# and I am writing abstract superclasses to encapsulate entity models and view models. The details aren't that important though, my problem is that I want these abstract classes to implement functions to map from any given view model to a corresponding entity model and vice versa.
I actaully already implemented such methods using generics and reflection, however I want to make it more neat. I got it all working by defining the EntityModel class as such:
public abstract class EntityModel
{
public TVM MapToViewModel<TVM, TEM>()
where TVM : ViewModel<TEM>, new()
where TEM : EntityModel, new()
{ (...) }
}
It really seems unnecessary to send the type of the entity model as an argument since the calling object will know it's own type and letting the calling code specify it opens up for stupid errors but I can't figure out how get rid of it. Defining the method as
public TVM MapToViewModel<TVM>()
where TVM : ViewModel<EntityModel>, new()
seems alot neater but it gives a compile time error since EntityModel is abstract. Is there any way to tell the compiler that it must be a derivative of EntityModel but not EntityModel itself? Or is there another better solution?
The ViewModel<> class is very similar and is defined as:
public abstract class ViewModel<T>
where T : EntityModel, new()
and it is working as intended.
Consider moving the mapping functionality outside of the entity and view model classes. This will result in more appropriate separation of concerns, as well as eliminating your current generic signature issue. e.g.:
public abstract class EntityModel
{
}
public abstract class ViewModel<T>
where T : EntityModel
{
}
public class ModelMapper<TEM, TVM>
where TEM : EntityModel, new()
where TVM : ViewModel<TEM>, new()
{
public virtual TVM MapToViewModel(TEM entityModel)
{
// Default implementation using reflection.
}
public virtual TEM MapToEntityModel(TVM viewModel)
{
// Default implementation using reflection.
}
}
Nicole beat me to it... was just thinking you could have a FromEntity instead, i.e:
public abstract class ViewModel<T>
where T : EntityModel, new()
{
public static ViewModel<T> FromEntity(T entity)
{
throw new NotImplementedException();
}
}
public abstract class EntityModel
{
//... properties, methods etc...
}
Or even have the ViewModel take the EntityModel in a constructor
EDIT
As per your comment - yes you are right, I have changed the parameter to T rather than EntityModel.
The nice thing about doing it this way is that the dependency is from ViewModel > EntityModel which is the way it should be really :)

Generic DAL / BLL Classes

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.

Categories

Resources