Skip to main content
3 of 7
deleted 4 characters in body

Object to object mapping verification - is this extension method useful?

In our .NET tests we use NSubstitute & ExpectedObjects.

Testing object expectations involves hand crafting large anonymous objects and when new properties are added we need to go back to these anonymous objects & update them.

Attempting below to get a fluent Object to DTO builder - which fails when a property is missed.

Here is the implementation:

        //CustomerCreatedEvent has all below properties 
        var exp1 = @event.ToDto<CustomerCreatedEvent,CustomerDetail>(
            x=> x.AggregateId.As("CustomerId"), 
            x => x.Email, 
            x => x.FirstName, 
            x => x.Surname);

        var exp2 = new {
                CustomerId= @event.AggregateId,
                @event.Email,      // if i comment out this line this test will still pass
                @event.FirstName,
                @event.Surname};

                
        exp1.ToExpectedObject().ShouldMatch(actual);
        exp2.ToExpectedObject().ShouldMatch(actual);

I have 2 questions:

  1. Is my code just adding 'noise'?
  2. Is the implementation code below sound?
 public static T2 ToDto<T1,T2>(this T1 obj, params Expression<Func<T1, dynamic>>[] items) where T1 : class
        {
            var eo = new ExpandoObject();
            var props = eo as IDictionary<String, object>;

            foreach (var item in items)
            {
                var member = item.Body as MemberExpression;
                var unary = item.Body as UnaryExpression;
                var body = member ?? (unary != null ? unary.Operand as MemberExpression : null);

                if (member != null && body.Member is PropertyInfo)
                {
                    var property = body.Member as PropertyInfo;
                    if (property != null)
                        props[property.Name] = obj.GetType().GetProperty(property.Name).GetValue(obj, null);
                }
                else if (unary != null)
                {
                    var ubody = (UnaryExpression)thing.Body;
                    var property = ubody.Operand as MemberExpression;
                    if (property != null)
                    {
                        props[property.Member.Name] = obj.GetType()
                            .GetProperty(property.Member.Name)
                            .GetValue(obj, null);
                    }
                    else // full expression with number funcs
                    {
                        var compiled = item.Compile();
                        var result = (KeyValuePair<string, object>)compiled.Invoke(obj);
                        props[result.Key] = result.Value;
                    }
                }
            }

            string json = JsonConvert.SerializeObject(eo);  // need json.net
            var anon = JsonConvert.DeserializeAnonymousType<object>(json, Activator.CreateInstance<T2>());
            return ((JObject)anon).ToObject<T2>();
        }