I am playing around with valueinjecter and wondering how do I do viewmodels to domains when the view model has a collection of viewmodels?
Say I have this domain
public class MyDomain
{
public IList<MyOtherDomain> MyOtherDomains {get; set;}
}
public class MyOtherDomain
{
public string Name {get; set;}
}
public class MyMasterVM
{
public IList<MyOtherVm> MyOtherDomains {get; set;}
}
public class MyOtherVm
{
public string Name {get; set;}
}
now how do I do my injecting? Do I need to manually map these with valueinjector?
public ActionResult Method(MyMasterVM vm)
{
MyDomain d = new MyDomain();
d.InjectFrom<UnflatLoopValueInjection>(vm);
}
Edit
After some playing around I got the simulator to work. However mine is different than the one in the tests
// sample test
public class FooBar : TypeMapper<Foo, Bar>
{
public override Bar Map(Foo source, Bar target)
{
base.Map(source, target);
target.NoConvention = source.Name + source.Xyz + source.Props;
return target;
}
}
[Test]
public void MapShouldMapCollectionPropertiesAndUseFooBarTypeMapper()
{
MapperFactory.AddMapper(new FooBar());
var foo = new Foo
{
Foos = new List<Foo>
{
new Foo{Name = "f1",Props = "v",Xyz = 19},
new Foo{Name = "f2",Props = "i",Xyz = 7},
new Foo{Name = "f3",Props = "v",Xyz = 3},
}
};
var bar = Mapper.Map<Foo, Bar>(foo);
Assert.AreEqual(foo.Foos.Count(), bar.Foos.Count());
var ffoos = foo.Foos.ToArray();
var bfoos = bar.Foos.ToArray();
for (var i = 0; i < ffoos.Count(); i++)
{
Assert.AreEqual(ffoos[i].Name, bfoos[i].Name);
Assert.AreEqual(ffoos[i].Name + ffoos[i].Xyz + ffoos[i].Props, bfoos[i].NoConvention);
}
}
// mine
public class Test : TypeMapper<IList<MyOtherVm>, IList<MyOtherDomain>>
{
public override IList<MyOtherDomain> Map(IList<MyOtherVm> source, IList<MyOtherDomain> target)
{
// not sure if I always have to call base
// mapping would happen here.
return base.Map(source, target);
}
}
MapperFactory.AddMapper(new Test());
IList<MyOtherDomain> otherDomains= new List<MyOtherDomain>();
MapperVj.Map(vm.MyOtherDomains , otherDomains);
I have to specify it is a IList otherwise it never seems to go into my overridden method.
I think you'd need to implement your own custom IValueInjection
injector. I am also basing this answer on a typo in your MyDomain
class.
MyDomain.MyOtherDomains : IList<MyOtherDomains>
and not
MyDomain.MyOtherDomains : IList<MyOtherVm>
So, the customer injection class could look like this (not 100% if there's a better way to do it)
public class CustomInjecter : IValueInjection
{
public object Map(object source, object target)
{
MyDomain result = new MyDomain();
result.MyOtherDomains = new List<MyOtherDomain>();
foreach (MyOtherVm vm in (source as MyMasterVM).MyOtherVMs)
{
MyOtherDomain od = new MyOtherDomain();
// inject commonly named properties of each "child" VM
od.InjectFrom(vm);
result.MyOtherDomains.Add(od);
}
return result;
}
}
In your controller, you can use it almost like you specified above (just change the injector type)
public ActionResult Method(MyMasterVM vm)
{
MyDomain d = new MyDomain();
d.InjectFrom<CustomInjecter>(vm);
// ...
}