I'm studding MVVM in C#.
I want to use Inversion of Control (IoC). I use the framework Unity.
I don't understand how to handling exception that could be raised from Data Access Layer.
Here a little easy example I do for study:
-- i have omitted the manage of Model validation (IDataErrorInfo) and Services for ViewModel (ex: DialogService) --
XAML View
<TextBox ... Text="{Binding Path=Id}" />
<TextBox ... Text="{Binding Path=Name}"/>
DESIGN APPLICATION
MODEL
{
public class User : INotifyPropertyChanged
{
private int _id;
public int Id
{
get{return _id;}
set
{
_id = value;
this.OnPropertyChanged("Id");
}
}
private string _name;
public string Name
{
get{return _name;}
set
{
_name = value;
this.OnPropertyChanged("Name");
}
}
public User(int i, string n)
{
_id = i;
_name = n;
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
}
DATA ACCESS LAYER
Interface
public interface IDataAccessLayer
{
Model.User GetUser();
}
Concrete class
public class ConcreteDataAccessLayer : IDataAccessLayer
{
public ConcreteDataAccessLayer(){}
Model.User IDataAccessLayer.GetUser()
{
//could throw Exception connecting with data source
}
}
BUSINESS LAYER
public class BusinessLayer
{
public BusinessLayer(IDataAccessLayer dataAccessLayer)
{
if (dataAccessLayer == null)
{
throw new ArgumentNullException("dataAccessLayer");
}
this._dataAccessLayer = dataAccessLayer;
}
private IDataAccessLayer _dataAccessLayer;
private QuestionStak.Model.User _user;
internal QuestionStak.Model.User User
{
get
{
if (_user == null)
_user = _dataAccessLayer.GetUser();
return _user;
}
}
}
VIEWMODEL
public class ViewModel : INotifyPropertyChanged
{
public ViewModel(BusinessLayer bl)
{
if (bl == null)
{
throw new ArgumentNullException("BusinessLayer");
}
_businessLayer = bl;
}
private BusinessLayer _businessLayer;
public int Id
{
get
{
return _businessLayer.User.Id;
}
set
{
_businessLayer.User.Id = value;
}
}
public string Name
{
get
{
return _businessLayer.User.Name;
}
set
{
_businessLayer.User.Name = value;
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
APPLICATION
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
//Inversion of control
IUnityContainer container = new UnityContainer();
//Created as singleton
container.RegisterType<IDataAccessLayer, ConcreteDataAccessLayer>(new ContainerControlledLifetimeManager());
container.RegisterType<BusinessLayer, BusinessLayer>(new ContainerControlledLifetimeManager());
MainWindow win = container.Resolve<MainWindow>();
win.DataContext = container.Resolve<ViewModel>();
win.Show();
}
}
Principles follow
- simple constructors (Unity catch all exception and follow http://blog.ploeh.dk/2011/03/03/InjectionConstructorsshouldbesimple/)
- ViewModel must hide Model structure
So I have a problem that I don't understands how to solve:
- If ConcreteDataAccessLayer can't load data (Ex: server not available) during loading of ViewModel the statement _dataAccessLayer.GetUser() throw the exception and in could not manage it (catch by Unity conteiner)
- If somewhere during the loading I manage the exception, the data binding cause the throw of a null exception because _businessLayer.User is null (unable to load the view)
Please, have someone a clean solution for this problem?
Thanks!