I have a repository pattern i created on top of the ado.net entity framework. When i tried to implement StructureMap to decouple my objects, i kept getting StackOverflowException (infinite loop?). Here is what the pattern looks like:
IEntityRepository where TEntity : class
Defines basic CRUD members
MyEntityRepository : IEntityRepository
Implements CRUD members
IEntityService where TEntity : class
Defines CRUD members which return common types for each member.
MyEntityService : IEntityService
Uses the repository to retrieve data and return a common type as a result (IList, bool and etc)
The problem appears to be with my Service layer. More specifically with the constructors.
public PostService(IValidationDictionary validationDictionary)
: this(validationDictionary, new PostRepository())
{ }
public PostService(IValidationDictionary validationDictionary, IEntityRepository<Post> repository)
{
_validationDictionary = validationDictionary;
_repository = repository;
}
From the controller, i pass an object that implements IValidationDictionary. And i am explicitly calling the second constructor to initialize the repository.
This is what the controller constructors look like (the first one creates an instance of the validation object):
public PostController()
{
_service = new PostService(new ModelStateWrapper(this.ModelState));
}
public PostController(IEntityService<Post> service)
{
_service = service;
}
Everything works if i don't pass my IValidationDictionary object reference, in which case the first controller constructor would be removed and the service object would only have one constructor which accepts the repository interface as the parameter.
I appreciate any help with this :) Thanks.
It looks like the circular reference had to do with the fact that the service layer was dependent on the Controller's ModelState and the Controller dependent on the Service layer.
I had to rewrite my validation layer to get this to work. Here is what i did.
Define generic validator interface like below:
public interface IValidator<TEntity>
{
ValidationState Validate(TEntity entity);
}
We want to be able to return an instance of ValidationState which, obviously, defines the state of validation.
public class ValidationState
{
private readonly ValidationErrorCollection _errors;
public ValidationErrorCollection Errors
{
get
{
return _errors;
}
}
public bool IsValid
{
get
{
return Errors.Count == 0;
}
}
public ValidationState()
{
_errors = new ValidationErrorCollection();
}
}
Notice that we have an strongly typed error collection which we need to define as well. The collection is going to consist of ValidationError objects containing the property name of the entity we're validating and the error message associated with it. This just follows the standard ModelState interface.
public class ValidationErrorCollection : Collection<ValidationError>
{
public void Add(string property, string message)
{
Add(new ValidationError(property, message));
}
}
And here is what the ValidationError looks like:
public class ValidationError
{
private string _property;
private string _message;
public string Property
{
get
{
return _property;
}
private set
{
_property = value;
}
}
public string Message
{
get
{
return _message;
}
private set
{
_message = value;
}
}
public ValidationError(string property, string message)
{
Property = property;
Message = message;
}
}
The rest of this is StructureMap magic. We need to create validation service layer which will locate validation objects and validate our entity. I'd like to define an interface for this, since i want anyone using validation service to be completely unaware of the StructureMap presence. Besides, i think sprinkling ObjectFactory.GetInstance() anywhere besides the bootstrapper logic a bad idea. Keeping it centralized is a good way to insure good maintainability. Anyway, i use the decorator pattern here:
public interface IValidationService
{
ValidationState Validate<TEntity>(TEntity entity);
}
And we finally implement it:
public class ValidationService : IValidationService
{
#region IValidationService Members
public IValidator<TEntity> GetValidatorFor<TEntity>(TEntity entity)
{
return ObjectFactory.GetInstance<IValidator<TEntity>>();
}
public ValidationState Validate<TEntity>(TEntity entity)
{
IValidator<TEntity> validator = GetValidatorFor(entity);
if (validator == null)
{
throw new Exception("Cannot locate validator");
}
return validator.Validate(entity);
}
#endregion
}
I'm going to be using validation service in my controller. We could move it to the service layer and have StructureMap use property injection to inject an instance of controller's ModelState to the service layer, but i don't want the service layer to be coupled with ModelState. What if we decide to use another validation technique? This is why i'd rather put it in the controller. Here is what my controller looks like:
public class PostController : Controller
{
private IEntityService<Post> _service = null;
private IValidationService _validationService = null;
public PostController(IEntityService<Post> service, IValidationService validationService)
{
_service = service;
_validationService = validationService;
}
}
Here i am injecting my service layer and validaton service instances using StructureMap. So, we need to register both in StructureMap registry:
ForRequestedType<IValidationService>()
.TheDefaultIsConcreteType<ValidationService>();
ForRequestedType<IValidator<Post>>()
.TheDefaultIsConcreteType<PostValidator>();
That's it. I don't show how i implement my PostValidator, but it's simply implementing IValidator interface and defining validation logic in the Validate() method. All that's left to do is call your validation service instance to retrieve the validator, call the validate method on your entity and write any errors to ModelState.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "PostId")] Post post)
{
ValidationState vst = _validationService.Validate<Post>(post);
if (!vst.IsValid)
{
foreach (ValidationError error in vst.Errors)
{
this.ModelState.AddModelError(error.Property, error.Message);
}
return View(post);
}
...
}
Hope i helped somebody out with this :)
I used a similar solution involving a generic implementor of IValidationDictionary uses a StringDictionary and then copied the errors from this back into the model state in the controller.
Interface for validationdictionary
public interface IValidationDictionary
{
bool IsValid{get;}
void AddError(string Key, string errorMessage);
StringDictionary errors { get; }
}
Implementation of validation dictionary with no reference to model state or anything else so structuremap can create it easily
public class ValidationDictionary : IValidationDictionary
{
private StringDictionary _errors = new StringDictionary();
#region IValidationDictionary Members
public void AddError(string key, string errorMessage)
{
_errors.Add(key, errorMessage);
}
public bool IsValid
{
get { return (_errors.Count == 0); }
}
public StringDictionary errors
{
get { return _errors; }
}
#endregion
}
Code in the controller to copy the errors from the dictionary into the model state. This would probably be best as an extension function of Controller.
protected void copyValidationDictionaryToModelState()
{
// this copies the errors into viewstate
foreach (DictionaryEntry error in _service.validationdictionary.errors)
{
ModelState.AddModelError((string)error.Key, (string)error.Value);
}
}
thus bootstrapping code is like this
public static void BootstrapStructureMap()
{
// Initialize the static ObjectFactory container
ObjectFactory.Initialize(x =>
{
x.For<IContactRepository>().Use<EntityContactManagerRepository>();
x.For<IValidationDictionary>().Use<ValidationDictionary>();
x.For<IContactManagerService>().Use<ContactManagerService>();
});
}
and code to create controllers is like this
public class IocControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return (Controller)ObjectFactory.GetInstance(controllerType);
}
}
Just a quick query on this. It's helped me out quite a lot so thanks for putting the answer up, but I wondered which namespace TEntity exists in? I see Colletion(TEntity) needs System.Collections.ObjectModel. My file compiles without anything further but I see your TEntity reference highlighted in Blue which suggests it has a class type, mine is Black in Visual Studio. Hope you can help. I'm pretty keen to get this working.
Have you found any way to seperate validation into the service layer at all? My gut tells me that validating in the Controller is a bit smelly but I've looked high and low to find a way to pass validation error messages back to the controller without tightly coupling the service layer to the controller and can't find anything. :(
Again, thanks for the great post!
Lloyd
Related
I am new to the MVVM architecture in Android, and I have some days with a doubt that I consider basic, but that I can't solve.
I proceed to discuss my problem:
I have an Entity, CustomerView (this entity is created from a DatabaseView):
#DatabaseView("select ... ")
public class CustomerView {
public String cardCode;
public String cardName;
public String cardFName;
...
Then, I have a Dao class:
#Dao
public interface OCRD_DAO {
...
#Query("SELECT * from CustomerView where cardCode= :cardCode")
LiveData<CustomerView> getCustomerViewByCardCode(String cardCode);
...
}
The repository class, makes use of the DAO class:
public LiveData<CustomerView> getCustomer(String cardCode){
return mOcrdDao.getCustomerViewByCardCode(cardCode);
}
The CustomerSheetViewModel class:
public class CustomerSheetViewModel extends BaseObservable {
private Repository mRepository;
public LiveData<CustomerView> mCustomer;
private MutableLiveData<String> _cardName;
#Bindable
public MutableLiveData<String> getCardName(){
return this._cardName;
}
public MutableLiveData<String> setCardName(String value){
// Avoids infinite loops.
if (mCustomer.getValue().cardName != value) {
mCustomer.getValue().cardName = value;
// React to the change.
saveData();
// Notify observers of a new value.
notifyPropertyChanged(BR._cardName);
}
}
public CustomerSheetViewModel (Application application, String cardCode) {
mRepository = new Repository(application);
this.mCustomer = mRepository.getCustomer(cardCode);
//Init MutableLiveData????
this._cardName = this.mCustomer.getValue().cardName;
//Null Exception, because this.mCustomer.getValue() is null
}
}
At this point, my problem occurs: when I initialise the CustomerView object, it is of type LiveData. However, if I want to make use of 2-way binding, I need an object of type MutableLiveData. So, I think I should create the MutableLiveData object with the data extracted from the database (i.e. from the call to the repository). When I try this (e.g. getValue().cardName) a null exception is thrown, since LiveData is asynchronous.
Finally, I could make use of this property in the layout:
android:text="#={customerSheetViewModel.cardName}"
I really appreciate any help, as I can't find any reference to 2-way binding when the data comes from a database read.
Thanks in advance.
[This is kind of an obvious question but I couldn't find anything about it - if someone could reference me, it'll be grand.]
In a WebAPI project:
public class MyObject
{
[PostSharp.Patterns.Contract.Required]
public string Name {get;set;}
}
public class MyController : ApiController
{
public HttpResponseMessage Post([FromBody]MyObject obj)
{
/// ...
}
}
During compilation, I guess PostSharp's validations put themselves in the setter of the property, so when obj is deserialised from the request's body, its fields aren't validated.
So, what's the best/clean way to validate that object?
Cheers
There is currently no clean way to achieve such validation as it is presumed that once-serialized object is already valid.
In order to force the validation logic, one would need to use ISerializationCallback interface's OnDeserialized method, go through properties and forcibly set them to their current value in order to enforce validation.
This can be done by a PostSharp aspect, but it would be certainly non-trivial. Other possibility is to use reflection/expression trees to achieve the same.
If you think that this would be a nice feature of PostSharp, you can vote PostSharp's UserVoice page.
As Daniel Balas wrote, there's no simple solution to trigger PostSharp's validations after deserializing an object, except implementing OnDeserialized method of ISerializationCallback interface. So I post an Aspect I wrote that deep copies public properties of objects one by one through reflection, and hence activating the validations in the setters.
[Serializable]
public sealed class ArgsValidationAspect : MethodInterceptionAspect
{
public override bool CompileTimeValidate(MethodBase method)
{
if (!method.GetParameters().Any(p => p.ParameterType.IsClass))
{
Message.Write(method, SeverityType.Error, "MY001", "Cannot apply HttpObjectValidationAspect to method '{0}'.", method);
return false;
}
return true;
}
public override void OnInvoke(MethodInterceptionArgs args)
{
foreach (var arg in args.Arguments)
{
try
{
RecursiveCopyInstance(arg);
}
catch (Exception e)
{
throw e.InnerException ?? e;
}
}
base.OnInvoke(args);
}
private static object RecursiveCopyInstance(object origin)
{
var type = origin.GetType();
var instance = Activator.CreateInstance(type);
foreach (var prop in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
{
var val = prop.GetValue(origin);
if (val != null && !prop.PropertyType.IsPrimitive && !prop.PropertyType.Equals(typeof(string)))
{
val = RecursiveCopyInstance(val);
}
prop.SetValue(instance, val);
}
return instance;
}
}
I am kinda unclear on how to pass data to other views. I gathered there are 3 ways to do this but I not sure how to do 2 of them.
Send data through messenger(not sure if you can send objects otherwise I can see thing getting pretty messy if you have to send like 10 pieces of data or something like that along).
Somehow pass the data through the constructor of the new view model. I say "somehow" as I am unclear how to do that when using an IOC container(in this case the built in one).
Passing the data through a parameter. I seen a couple of tutorials that show you how to do navigation for the windows phone but none really talk about parameter passing. I am guessing this would still be an option.
From what I heard is that Option 1 is sort of the old way of doing it. Option 2 seems to be a newer way and better way to do it but I cannot find any examples on people showing how to do it.
I don't know how to do it because the Ioc should be creating the instance of the view so how do you pass in data into it when that data does not exist?
The two main ways I do this is:
1)Use the messenger:
Sender class:
public class TrafficLight
{
public string Color{get;set;}
public TimeSpand Duration{get;set;}
}
public class TrafficLightService
{
public void SendLight(TrafficLight light)
{
Messenger.Default.Send(light);
}
}
Receiver:
public class MyViewModel
{
public MyViewModel()
{
Messenger.Default.Register<TrafficLight>(DoSomethingWithTrafficLight);
}
private void DoSomethingWithTrafficLight(TrafficLight light)
{
}
}
What happens here is that the source object is using the Messenger as an event broker. Object A doesn't need to know about object B, they just both need to know about the messenger.
2)
Just use dependency injection:
public class TrafficLight
{
public string Color{get;set;}
public TimeSpand Duration{get;set;}
}
public class LightEventArgs:EventArgs
{
public LightEventArgs(TrafficLight light)
{
_light=light;
}
public TrafficLight Light{get{return _light;}}
}
public interface ITrafficLightService
{
void SendLight(TrafficLight light);
public event EventHandler<LightEventArgs> TrafficLightSet;
}
public class TrafficLightService
{
public void SendLight(TrafficLight light)
{
Messenger.Default.Send(light);
}
public event EventHandler<LightEventArgs> TrafficLightSet;
}
public class TrafficLightSenderViewModel
{
public TrafficLightSenderViewModel(ITrafficLightService trafficLightService)
{
_trafficLightService=trafficLightService;
_trafficLightService.Send(new TrafficLight{Color="Red"});
}
}
public class TrafficLightReceiverViewModel
{
public TrafficLightReceiverViewModel(ITrafficLightService trafficLightService)
{
_trafficLightService=trafficLightService;
_trafficLightService.TrafficLightSet+= TrafficLightNotification;
}
private void TrafficLightNotification(TrafficLightEventArgs args)
{
DoSomethingWithTheLight(args.Light);
}
}
public class ViewModelLocator
{
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<ITrafficLightService, Design.TrafficLightService>();
}
else
{
SimpleIoc.Default.Register<ITrafficLightService, TrafficLightService>();
}
SimpleIoc.Default.Register<TrafficLightSenderViewModel>();
SimpleIoc.Default.Register<TrafficLightReceiverViewModel>();
}
public MainViewModel Sender
{
get { return SimpleIoc.Default.GetInstance<TrafficLightSenderViewModel>(); }
}
public MainViewModel Receiver
{
get { return SimpleIoc.Default.GetInstance<TrafficLightReceiverViewModel>(); }
}
}
This is a bigger example and more complex.
Lets walk through this step by step:
In MVVM Light we use the ViewModelLocator for 2 things: 1)To register all our viewmodels and services.
Provide a way to allow the View to get a viewmodel in XAML
When we try to resolve a ViewModel
SimpleIoc.Default.GetInstance<TrafficLightReceiverViewModel>();
SimpleIoc looks at whether the viewmodel has any dependencies. In our case we do, we need an ITrafficLightService for both our viewmodels. What happens is that SimpleIoc sees if it can resolve that class and, in the process, checks to see if ITrafficLightService has any dependencies that need resolving as well. If SimpleIoc can resolve the chain of dependencies required to instantiate your viewmodel it does so and then hands back a fully built object.
I want to create a wrapper class so that all queries should not be in controller. Currently select queries are placed in Controller. But I want to create another layer for abstraction.
I already created a viewmodel class. But wrapper class is something else.
How do I do that?
I don't do any queries directly in my controllers. I have a service layer which my controller would call, and each service layer would do a call to the repository to insert, update or delete data or bring back data.
The sample code below uses ASP.NET MVC3 and Entity Framework code first. Lets assume you want to bring back all the countries and use it for whatever reason in your controller/view:
My database context class:
public class DatabaseContext : DbContext
{
public DbSet<Country> Countries { get; set; }
}
My country repository class:
public class CountryRepository : ICountryRepository
{
DatabaseContext db = new DatabaseContext();
public IEnumerable<Country> GetAll()
{
return db.Countries;
}
}
My service layer that calls my repository:
public class CountryService : ICountryService
{
private readonly ICountryRepository countryRepository;
public CountryService(ICountryRepository countryRepository)
{
// Check for nulls on countryRepository
this.countryRepository = countryRepository;
}
public IEnumerable<Country> GetAll()
{
// Do whatever else needs to be done
return countryRepository.GetAll();
}
}
My controller that would call my service layer:
public class CountryController : Controller
{
private readonly ICountryService countryService;
public CountryController(ICountryService countryService)
{
// Check for nulls on countryService
this.countryService = countryService;
}
public ActionResult List()
{
// Get all the countries
IEnumerable<Country> countries = countryService.GetAll();
// Do whatever you need to do
return View();
}
}
There are lots of info on the internet on how to get you data and display it, inserting, editing, etc. A good place to start is at http://www.asp.net/mvc. Work through their tutorials, it will do you good. All the best.
Does anyone know if it's possible to use Ninject to resolve any unresolved abstract dependencies outside of the instantiation process? I've just been looking into constructor injection vs property/method/field injection, but it looks to me as though Ninject is still expecting to be the creator of the type using the IKernel.Get<>() method.
Basically, we're using MVC3 to build our product, and we've come up against a situation where we want the default ModelBinder to map form values to an instance of the object, and then be able to call a method on the submitted ViewModel that is dependent on an abstract interface e.g.
public class InviteFriend {
[Required]
public string EmailAddress { get; set; }
public void Execute() {
var user = IUserRepository.GetUser(this.EmailAddress);
if (user == null) {
IUserRepository.SaveInvite(this.EmailAddress);
}
MailMessage toSend = new MailMessage(); // Obviously some logic to prepare the body, subject and other mail properties
SmtpClient.Send(toSend);
}
}
where the controller action would receive InviteFriend as the method argument. We want Ninject to be able to resolve that IUserRepository dependency, but I can't quite work out how to since the object itself is instantiated by the MVC ModelBinder rather than Ninject IKernel.Get<>().
Maybe the solution is a Ninject-based ModelBinder, or does that seem a really bad idea?
EDIT TO ADD: After the comments below, I realise that my hastily mocked-up code sample doesn't really reflect what we're facing. I've updated the code sample to reflect that the logic for InviteFriend.Execute() is more complex than just calling a method on one repository. Potentially, this is logic representing a discrete task that could co-ordinate interactions between multiple different domain objects and multiple repositories. The repositories are defined abstractly, and ideally would be resolved by Ninject.
I think what you are looking for is somewhat the following scenario:
public class InviteFriend {
[Required]
public string EmailAddress { get; set; }
// More information
}
public interface ICommand {
void Execute();
}
public class InviteFriendCommand : ICommand
{
public InviteFriend(InviteFriend info, IUserRepository userRepo, IMailSender mailSender) {
this.inviteFriend = info;
this.userRepo = userRepo;
this.mailSender = mailSender;
}
public void Execute() {
var user = this.userRepo.GetUser(this.inviteFriend.EmailAddress);
if (user == null) {
this.userRepo.SaveInvite(this.inviteFriend.EmailAddress);
}
MailMessage toSend = new MailMessage(); // Obviously some logic to prepare the body, subject and other mail properties
this.mailSender.Send(toSend);
}
}
public interface ICommandFactory {
ICommand CreateInviteFriendCommand(InviteFriend info);
}
public class CommandFactory {
public CommandFactory(IResolutionRoot resolutionRoot) {
this.resolutionRoot = resolutionRoot;
}
ICommand CreateInviteFriendCommand(InviteFriend info) {
this.resolutionRoot.Get<InviteFriendCommand>(new ConstructorArgument("info", info));
}
}
public class YourController {
// Somewhere
var command = this.commandFactory.CreateInviteFriendCommand(info);
command.Execute();
}
public class YourModule : NinjectModule {
override Load() {
Bind<IUserRepository>().To<UserRepo>().InRequestScope();
Bind<ICommandFactory>().To<CommandFactory>().InRequestScope();
Bind<InviteFriendCommand>().ToSelf().InRequestScope();
}
}
Forgive me when you need to tweak it a bit. I hacked it together with my out of brain compiler ;)
Thank you for all your comments, but I've subsequently found the information I was looking for.
The answer is that it is possible to inject dependencies post-instantiation with Ninject. The solution is as follows:
public class InviteFriend {
[Inject]
public IUserRepository UserRepo { get; set; }
[Required]
public string EmailAddress { get; set; }
public void Execute() {
var user = UserRepo.GetUser(this.EmailAddress);
if (user == null) {
UserRepo.SaveInvite(this.EmailAddress);
}
MailMessage toSend = new MailMessage(); // Obviously some logic to prepare the body, subject and other mail properties
SmtpClient.Send(toSend);
}
}
With client code then using the Ninject kernel as follows:
IKernel container = new StandardKernel(new ModuleWithMyBindings());
container.Inject(instanceOfInviteFriend);
The code itself is a bit more sophisticated than that i.e. I'm not instantiating a new IKernel each time I need it.
I realise that this is architecturally less pure than some of the suggestions put forward in comments, but in the spirit of YAGNI, this is good enough for now and we can always refactor later on with some of the good suggestions in Daniel's answer. However, this was a question about the capabilities of Ninject rather than an architectural review question, and this is what I consider the answer to my own question :)