带操作符的泛型值和类型比较器
本文关键字:类型 比较器 泛型 操作符 | 更新日期: 2023-09-27 18:04:52
我有一个业务逻辑,基于预定义的条件(OperatorType
和比较值),验证它是真还是假。这里的问题是值是"类型化"的,并且带有操作符(大于/小于/等于等)。
如果ValueType
为Integer,则先将值和比较值转换为Integer
,再以OperatorType
为基础进行比较。
我想知道我是否可以有一个通用函数,传递CompareValue
, Value
, ValueType
, OperatorType
并返回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;
}
}
废话不多说,让我们开始吧:
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; }
}
}
这可以做很多改进(更好的类型检查、文化信息感知和错误处理)。但是,它是一个开始