2013-03-19 55 views
1

我有一個基於預定義條件(OperatorType和比較值)的業務邏輯,驗證它是真或假。這裏的問題是值是「鍵入」,並與運算符(大/小/等)等。運算符的通用值和類型比較器

如果ValueType是整數,那麼值和比較值需要先轉換爲Integer,然後再根據OperatorType做比較。

我想知道如果我能有一個通用功能,傳球CompareValueValueValueTypeOperatorType並返回真/假。

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; } 
    } 
} 
+1

這是什麼問題?到**編輯**是的,你可以編寫這樣的功能。你有什麼嘗試? – sehe 2013-03-19 11:35:12

+0

@sehe對不起,我更新了我的問題。我想知道是否可以有一個通用函數,傳遞CompareValue,Value,ValueType,OperatorType並返回true/false。 – James 2013-03-19 11:37:58

+0

@sehe,我試着用新的比較器,但它是一個基類沒有實現。我嘗試基於ValueType的Convert.ChangeType,但它仍然錯過了比較的最後一步。 – James 2013-03-19 11:48:29

回答

1

事不宜遲,讓你開始:

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; } 
    } 
} 

這可能有很多的改進(更好的類型檢查,CultureInfo的認識和錯誤處理)做的。但是,這是一個開始

+0

我得到了RuntimeBinderException:運算符'> ='不能應用於'int'和'object'類型的操作數,這與我今天面臨的情況類似,因爲對象無法與值類型進行比較。 – James 2013-03-19 11:57:45

+0

啊哈。那麼最好讓它動態。編輯。 – sehe 2013-03-19 11:58:40

+0

對,它現在起作用,它有點邪惡,因爲它利用動態,但足夠整齊,並完成工作。 – James 2013-03-19 12:01:56

2
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; 
    } 
} 
+0

不錯,我不知道'Convert.ChangeType'存在。 – sehe 2013-03-19 12:07:49

+0

@sehe,這正是我使用但無法實現的功能.... – James 2013-03-19 12:26:22

+0

@Yaugen Vlasau,你的代碼毫無疑問的工作,但它不是泛化,以驗證對ValueType。附加代碼是必需的。 – James 2013-03-19 12:33:52