简体   繁体   中英

Generic value and type comparer with operators

I have a business logic, base on the pre-defined condition ( OperatorType and compare value), validate if it is true or false. The problem here is the value is "typed", and with operator (greater/less/equal etc).

If ValueType is Integer, then the value and compare value need to converted to Integer first, then base on OperatorType , do comparison.

I would like to know if I can have a general function, passing CompareValue , Value , ValueType , OperatorType and return true/false.

using System;
using System.Collections.Generic;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            var compare1 = 3;
            var foo1 = new Foo { Value = "2", OperatorType = OperatorTypes.GreaterOrEqual, ValueType = ValueTypes.Long };
            //compare compare1 and foo1.Value, output should be false (2 < 3)

            var compare2 = true;
            var foo2 = new Foo { Value = "True", OperatorType = OperatorTypes.Equal, ValueType = ValueTypes.Bool };
            //compare compare2 and foo2.Value, output should be true (true = true)

            var compare3 = DateTime.Parse("2013-03-19 15:00");
            var foo3 = new Foo { Value = "2013-03-19 16:00", OperatorType = OperatorTypes.Less, ValueType = ValueTypes.Date };
            //compare compare3 and foo3.Value, output should be false (2013-03-19 16:00 < 2013-03-19 15:00)
        }
    }

    public enum OperatorTypes : uint
    {
        Equal = 1,
        Greater = 2,
        GreaterOrEqual = 3,
        Less = 4,
        LessOrEqual = 5
    }

    public enum ValueTypes : uint
    {
        None = 0,
        Integer = 1,
        Long = 2,
        Numeric = 3,
        Date = 4,
        Text = 5,
        Bool = 6
    }

    class Foo
    {
        public string Value { get; set; }
        public ValueTypes ValueType { get; set; }
        public OperatorTypes OperatorType { get; set; }
    }
}
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Compare<double>("123.1", 125.3, (a, b) => a > b));
        Console.WriteLine(Compare<DateTime>("19/03/2013", DateTime.Now, (a, b) => a == b));
    }

    private static bool Compare<T>(string valueAsString, T valueToComapare, Func<T,T,bool> check)
    {
        var asObject = (T)Convert.ChangeType(valueAsString, typeof(T));

        if (asObject != null)
        {
            return check(asObject, valueToComapare);
        }

        return false;
    }
}

Without further ado, to get you started:

using System;
using System.Diagnostics;
using System.Collections.Generic;

namespace Test
{
    class Program
    {
        public static dynamic CompareVal(Foo logic)
        {
            switch(logic.ValueType)
            {
                case ValueTypes.Integer: return Convert.ToInt32(logic.Value);
                case ValueTypes.Long:    return Convert.ToInt64(logic.Value);
                case ValueTypes.Numeric: return Convert.ToDecimal(logic.Value);
                case ValueTypes.Date:    return Convert.ToDateTime(logic.Value);
                case ValueTypes.Text:    return logic.Value;
                case ValueTypes.Bool:    return Convert.ToBoolean(logic.Value);
            }
            throw new InvalidProgramException("Unsupported ValueType");
        }

        public static bool Evaluate(dynamic val, Foo logic)
        {
            dynamic cmpval = CompareVal(logic);

            switch(logic.OperatorType)
            {
                case OperatorTypes.Equal:          return val == cmpval;
                case OperatorTypes.Greater:        return val >  cmpval;
                case OperatorTypes.GreaterOrEqual: return val >= cmpval;
                case OperatorTypes.Less:           return val <  cmpval;
                case OperatorTypes.LessOrEqual:    return val <= cmpval;
            }

            return false;
        }

        static void Main(string[] args)
        {
            //compare compare1 and foo1.Value, output should be false (2 < 3)
            Debug.Assert(false == Evaluate(3, new Foo 
                        { 
                            Value = "2", 
                            OperatorType = OperatorTypes.GreaterOrEqual, 
                            ValueType = ValueTypes.Long 
                        }));

            //compare compare2 and foo2.Value, output should be true (true = true)
            Debug.Assert(true == Evaluate(true, new Foo 
                        { 
                            Value = "True", 
                            OperatorType = OperatorTypes.Equal, 
                            ValueType = ValueTypes.Bool 
                        }));

            //compare compare3 and foo3.Value, output should be false (2013-03-19 16:00 < 2013-03-19 15:00)
            Debug.Assert(false == Evaluate(DateTime.Parse("2013-03-19 15:00"), new Foo 
                        { 
                            Value = "2013-03-19 16:00", 
                            OperatorType = OperatorTypes.Less, 
                            ValueType = ValueTypes.Date 
                        }));
        }
    }

    public enum OperatorTypes : uint
    {
        Equal = 1,
        Greater = 2,
        GreaterOrEqual = 3,
        Less = 4,
        LessOrEqual = 5
    }

    public enum ValueTypes : uint
    {
        None = 0,
        Integer = 1,
        Long = 2,
        Numeric = 3,
        Date = 4,
        Text = 5,
        Bool = 6
    }

    class Foo
    {
        public string Value { get; set; }
        public ValueTypes ValueType { get; set; }
        public OperatorTypes OperatorType { get; set; }
    }
}

This could do with a lot of improvement (better type checking, CultureInfo awareness and error handling). But, it's a start

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM