سؤال

I'm trying to use ValueInjector to flatten a class and to have it also copy across values from Nullable<int>'s to int's.

Eg given the following (contrived) classes:

class CustomerObject
{
    public int CustomerID { get; set; }
    public string CustomerName { get; set; }
    public OrderObject OrderOne { get; set; }
}

class OrderObject
{
    public int OrderID { get; set; }
    public string OrderName { get; set; }
}

class CustomerDTO
{
    public int? CustomerID { get; set; }
    public string CustomerName { get; set; }
    public int? OrderOneOrderID { get; set; }
    public string OrderOneOrderName { get; set; }
}

I would like to flatten an instance of CustomerObject to a CustomerDTO, with it ignoring the fact that the CustomerID and OrderID's are of different types (one is nullable one isn't).

So I would like to do this:

CustomerObject co = new CustomerObject() { CustomerID = 1, CustomerName = "John Smith" };
co.OrderOne = new OrderObject() { OrderID = 2, OrderName = "test order" };

CustomerDTO customer = new CustomerDTO();
customer.InjectFrom<>(co);

And then have all of the properties populated, specifically:

customer.CustomerID 
customer.OrderOneOrderID 
customer.OrderOneOrderName

I realise I can use FlatLoopValueInjection to flatten out the object, and I'm using this NullableInjection class:

public class NullableInjection : ConventionInjection
{
    protected override bool Match(ConventionInfo c)
    {
        return c.SourceProp.Name == c.TargetProp.Name &&
                (c.SourceProp.Type == c.TargetProp.Type
                || c.SourceProp.Type == Nullable.GetUnderlyingType(c.TargetProp.Type)
                || (Nullable.GetUnderlyingType(c.SourceProp.Type) == c.TargetProp.Type
                        && c.SourceProp.Value != null)
                );
    }

    protected override object SetValue(ConventionInfo c)
    {
        return c.SourceProp.Value;
    }
}

Basically I'd like to combine the two. Is this possible?

هل كانت مفيدة؟

المحلول

you could do this by overriding the TypesMatch method:

    public class MyFlatInj : FlatLoopValueInjection
    {
        protected override bool TypesMatch(Type sourceType, Type targetType)
        {
            var snt = Nullable.GetUnderlyingType(sourceType);
            var tnt = Nullable.GetUnderlyingType(targetType);

            return sourceType == targetType
                   || sourceType == tnt
                   || targetType == snt
                   || snt == tnt;
        }
    }

or by grabbing the FlatLoopValueInjection from the source code and edit it as you need (it's about 10 lines)

نصائح أخرى

ValueInjecter V3 removes FlatLoopValueInjection. Below is update of Omu's answer.

public class FlatLoopInjectionNullable : Omu.ValueInjecter.Injections.FlatLoopInjection
{
    protected override bool Match(string propName, PropertyInfo unflatProp, PropertyInfo targetFlatProp)
    {
        var snt = Nullable.GetUnderlyingType(unflatProp.PropertyType);
        var tnt = Nullable.GetUnderlyingType(targetFlatProp.PropertyType);

        return propName == unflatProp.Name
            && unflatProp.GetGetMethod() != null
            && (unflatProp.PropertyType == targetFlatProp.PropertyType
                || unflatProp.PropertyType == tnt
                || targetFlatProp.PropertyType == snt
                || (snt != null && snt == tnt));
    }
}

Call it like this:

target.InjectFrom<ValueInjecterNullable>(source);
// !!! THIS IS FOR LoopInjection not FlatLoopValueInjection !!!
public class NullableInjection : LoopInjection
{
    public NullableInjection() : base() { }

    public NullableInjection(string[] ignoredProps) : base(ignoredProps) { }

    protected override bool MatchTypes(Type source, Type target)
    {
        // This is the most likely scenario test for it first.
        bool result = source == target;
        // if not a type match then lets do more expensive tests.
        if (!result)
        {
            var snt = Nullable.GetUnderlyingType(source);
            var tnt = Nullable.GetUnderlyingType(target);

            // Make sure that underlying types have not reverted to null       
            // this will cause false positives.
            result = ((source == target)
                   || ((tnt != null) && source == tnt)
                   || ((snt != null) && target == snt)
                   || ((tnt != null) && snt == tnt));
        }
        return result;
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top