Nullable types

Jul 1, 2010 at 7:02 PM

I noticed that if my DTO has a nullable type but my class is not nullable, ValueInjecter won't address that field without extending LoopValueInjection.  That's understandable since the destination type won't know how to handle null, but what about going the other way?  I would think you could safely go from a bool? to a bool without an issue, which should preclude me from having to extend the LoopValueInjection.  Is that possible?

Granted, there aren't many instances where I have a nullable column in the database that doesn't correspond to a nullable property on the business object, but it does happen.

Josh

Coordinator
Jul 1, 2010 at 8:16 PM

Here you go

using System;
using System.ComponentModel;
using NUnit.Framework;
using Omu.ValueInjecter;

namespace Tests
{
    [TestFixture]
    public class NullablesTests
    {
        public class E
        {
            public bool b { get; set; }
            public int i { get; set; }
            public int j { get; set; }
            public int x { get; set; }
        }

        public class D
        {
            public bool? b { get; set; }
            public int? i { get; set; }
            public int? j { get; set; }
            public int x { get; set; }
        }

        public class NullablesToNormal : ValueInjection
        {
            protected override void Inject(object source, object target, PropertyDescriptorCollection sourceProps, PropertyDescriptorCollection targetProps)
            {
                for (var i = 0; i < sourceProps.Count; i++)
                {
                    var s = sourceProps[i];
                    if (Nullable.GetUnderlyingType(s.PropertyType) == null) continue;
                    var type = s.PropertyType.GetGenericArguments()[0];
                    var t = targetProps.GetByName(s.Name);
                    if (t == null) continue;
                    if (t.PropertyType != type) continue;

                    var value = s.GetValue(source);
                    t.SetValue(target, value);
                }
            }
        }

        public class NormalToNullables : ValueInjection
        {
            protected override void Inject(object source, object target, PropertyDescriptorCollection sourceProps, PropertyDescriptorCollection targetProps)
            {
                for (var i = 0; i < sourceProps.Count; i++)
                {
                    var s = sourceProps[i];
                    var t = targetProps.GetByName(s.Name);
                    if (t == null) continue;

                    if (Nullable.GetUnderlyingType(t.PropertyType) == null) continue;
                    var type = t.PropertyType.GetGenericArguments()[0];
                    if (s.PropertyType != type) continue;

                    var value = s.GetValue(source);
                    t.SetValue(target, value);
                }
            }
        }

        [Test]
        public void NullablesToNormalTest()
        {
            var d = new D { b = true, i = 1, x = 3213213 };
            var e = new E();

            e.InjectFrom<NullablesToNormal>(d);

            e.i.IsEqualTo(1);
            e.b.IsEqualTo(true);
            e.x.IsEqualTo(0);
            e.j.IsEqualTo(0);
        }

        [Test]
        public void NormalToNullablesTest()
        {
            var e = new E { b = true, i = 1, x = 3213213, j = 123 };
            var d = new D();

            d.InjectFrom<NormalToNullables>(e);

            d.i.IsEqualTo(1);
            d.b.IsEqualTo(true);
            d.x.IsEqualTo(0);
            d.j.IsEqualTo(123);
        }

    }
}

cya

Omu

Jul 1, 2010 at 9:06 PM

You're the man.  The more I work with this tool the more I like it.

Coordinator
Jul 5, 2010 at 2:02 PM

Hello

just an update: with the new version 1.9.3 you can write those 2 injections like this:

        public class NullablesToNormal : LoopValueInjection
        {
            protected override bool TypesMatch(Type sourceType, Type targetType)
            {
                var type = Nullable.GetUnderlyingType(sourceType);
                if(type == null) return false;
                return targetType == type;
            }
        }

        public class NormalToNullables: LoopValueInjection
        {
            protected override bool TypesMatch(Type sourceType, Type targetType)
            {
                var type = Nullable.GetUnderlyingType(targetType);
                if (type == null) return false;
                return sourceType == type;
            }
        }

 

kthnxbye

Omu