2

After working with AutoMapper I came across ValueInjecter on this site. I am trying it out but I am stuck on what is probably a very simple scenario.

But before I dig into the code sample, does anyone know if ValueInjecter works in a Medium-Trust web environment? (Like Godaddy?)

Ok, onto the code! I have the following models:

public class NameComponent 
{
    public string First { get; set; }
    public string Last { get; set; }
    public string MiddleInitial { get; set; }
}
public class Person
{
    public NameComponent Name { get; set; }
}

that I want to map to the following DTO:

public class PersonDTO : BaseDTO
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set { NotifyPropertyChanged(() => FirstName, ref _firstName, value); }
    }

    private string _middleInitial;
    public string MiddleInitial
    {
        get { return _middleInitial; }
        set { NotifyPropertyChanged(() => MiddleInitial, ref _middleInitial, value); }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set { NotifyPropertyChanged(() => LastName, ref _lastName, value); }
    }
}

So when I want to Map from Model to DTO I need a Model.Name.First -> DTO.FirstName and when going from DTO to Model I need FirstName -> Name.First. From my understanding this is not a simple Flatten/UnFlatten, because the words also reverse themselves, ie: FirstName <--> Name.First. So First and Last names could use the same kind of rule, but what about MiddleInitial? Model.Name.MiddleInitial -> DTO.MiddleInitial.

I see there are some plugins, but none of them seem to do what I would want. Has anyone else come across this scenario?

Omu
  • 69,856
  • 92
  • 277
  • 407
NYCChris
  • 649
  • 5
  • 13

1 Answers1

1

the basic idea is that I match the Name with the FirstName, I take this as a pivot point, and in the method that usually sets the value to just one (FirstName) property I set it to 3 properties - that's for the FromNameComp

in the ToNameComp i match the same properties but I take the value from 3 and create one and set it

    public class SimpleTest
    {
        [Test]
        public void Testit()
        {
            var p = new Person { Name = new NameComponent { First = "first", Last = "last", MiddleInitial = "midd" } };
            var dto = new PersonDTO();
            dto.InjectFrom<FromNameComp>(p);

            Assert.AreEqual(p.Name.First, dto.FirstName);
            Assert.AreEqual(p.Name.Last, dto.LastName);
            Assert.AreEqual(p.Name.MiddleInitial, dto.MiddleInitial);

            var pp = new Person();
            pp.InjectFrom<ToNameComponent>(dto);

            Assert.AreEqual(dto.LastName, pp.Name.Last);
            Assert.AreEqual(dto.FirstName, pp.Name.First);
            Assert.AreEqual(dto.MiddleInitial, pp.Name.MiddleInitial);

        }

        public class FromNameComp : ConventionInjection
        {
            protected override bool Match(ConventionInfo c)
            {
                return c.SourceProp.Name == "Name" && c.SourceProp.Type == typeof(NameComponent)
                    && c.TargetProp.Name == "FirstName"
                       && c.SourceProp.Value != null;
            }

            protected override object SetValue(ConventionInfo c)
            {
                dynamic d = c.Target.Value;
                var nc = (NameComponent)c.SourceProp.Value;
                //d.FirstName = nc.First; return nc.First does this
                d.LastName = nc.Last;
                d.MiddleInitial = nc.MiddleInitial;
                return nc.First;
            }
        }

        public class ToNameComponent : ConventionInjection
        {
            protected override bool Match(ConventionInfo c)
            {
                return c.TargetProp.Name == "Name" && c.TargetProp.Type == typeof(NameComponent)
                       && c.SourceProp.Name == "FirstName";
            }

            protected override object SetValue(ConventionInfo c)
            {
                dynamic d = c.Source.Value;
                var nc = new NameComponent { First = d.FirstName, Last = d.LastName, MiddleInitial = d.MiddleInitial };
                return nc;
            }
        }

        public class NameComponent
        {
            public string First { get; set; }
            public string Last { get; set; }
            public string MiddleInitial { get; set; }
        }

        public class Person
        {
            public NameComponent Name { get; set; }
        }

        public class PersonDTO
        {
            public string FirstName { get; set; }
            public string MiddleInitial { get; set; }
            public string LastName { get; set; }
        }
}

But before I dig into the code sample, does anyone know if ValueInjecter works in a Medium-Trust web environment? (Like Godaddy?)

it doesn't use reflection.emit so it should work

Omu
  • 69,856
  • 92
  • 277
  • 407
  • I can't wait to try this out! Thank you for the reply. Looking at the solution bring me to another question. I see that in order to map from Person -> PersonDTO requires something like this. var pp = new Person(); pp.InjectFrom(dto); pp.InjectFrom(dto); Is there any sort of facility that will allow me to setup a map to register this kind of stuff at startup? – NYCChris Mar 03 '11 at 13:59
  • something like `var injecter = new ValueInjecter(); injecter.Define( (person,dto,injecter) => { injecter.Inject(dto,person); injecter.Inject(Inject(dto, person); }); ` then later on in use it would just be this... pp.InjectFrom(dto); – NYCChris Mar 03 '11 at 13:59
  • @NYCChris :) no, thats automapper, but you can create your own mapper class and put there whatever injections you need – Omu Mar 03 '11 at 14:45
  • Yup... after I abandoned automapper I started writing my own until I found ValueInjecter. I can reuse some of what I wrote to create my defined injection idea. **BTW: You code worked! Thank you!** – NYCChris Mar 03 '11 at 14:48