在运行时知道类型时,如何将db中的值映射到我的对象?

时间:2011-10-27 15:52:45

标签: c#

我的数据库有一个表格如下:

conditionID, conditionType, conditionValue

ConditionType是一个枚举,其值为Integer,String,DateTime等。

ConditionValue存储为字符串。

现在我想将这一行封装在一个类中,以便我可以在ConditionValue上执行比较,所以这就像EqualTo,GreaterThan,LessThan等。

目前我的设计不正确,因为我有像(otherValue这样的方法是我正在比较的价值):

GreaterThan(string value, string otherValue);
GreaterThan(int value, int otherValue);
GreaterThan(DateTime value, DateTime otherValue);

我可以以某种方式创建一个包含此信息的ConditionValue类,以便我可以这样做:

GreaterThan(IConditionValue condition, IConditionValue otherValue)

5 个答案:

答案 0 :(得分:2)

应该可以使用自适应对象模型或类型对象模式轻松建模。但是,对你的情况来说可能会过度杀戮。

http://adaptiveobjectmodel.com/

http://www.cs.ox.ac.uk/jeremy.gibbons/dpa/typeobject.pdf

它允许您在运行时重新配置模型,随意添加/删除行为,定义规则等。

答案 1 :(得分:1)

这是一个非常天真的例子。

public class ConditionValue
{
    private object value;
    private IValueType valueType;

    public ConditionValue(object value, IValueType valueType)
    {
        this.value = value;
        this.valueType = valueType;
    }

    public bool GreaterThan(ConditionValue cv)
    {
        return valueType.GreaterThan(this.value, cv.value);
    }
}

public interface IValueType
{
    bool GreaterThan(object left, object right);
}

public class IntegerType : IValueType
{
    public bool GreaterThan(object left, object right)
    {
        return (int)left > (int)right;
    }
}

答案 2 :(得分:1)

您提到的所有类型都实现了IComparable,因此您可以简单地假设类型是IComparable并使用CompareTo()方法。

bool GreaterThan(IComparable value, IComparable otherValue)
{
    return value.CompareTo(otherValue) > 0;
}

答案 3 :(得分:1)

    public enum ValueType
    {
        String = 0,
        Integer = 1,
        CustomDataType = 3
    }

    public interface IValueType : IComparer<object>
    {
        string ToString(object obj);
    }

    public class IntegerValueType : IValueType
    {
        public int Compare(object left, object right)
        {
            return ((int)left).CompareTo((int)right);
        }

        public string ToString(object obj)
        {
            return ((int)obj).ToString();
        }
    }

    public class StringValueType : IValueType
    {
        public int Compare(object left, object right)
        {
            return ((string)left).CompareTo((string)right);
        }

        public string ToString(object obj)
        {
            return ((string)obj).ToString();
        }
    }

    public class Value : IComparable<Value>
    {
        private object value;
        private IValueType valueType;

        public Value(object value, IValueType valueType)
        {
            this.value = value;
            this.valueType = valueType;
        }

        public static implicit operator Value(string value)
        {
            return ValueFactory.Create(value, ValueType.String);
        }

        public int CompareTo(Value obj)
        {
            return this.valueType.Compare(this.value, obj.value);
        }

        public static bool operator <(Value left, Value right)
        {
            return left.CompareTo(right) == -1;
        }

        public static bool operator >(Value left, Value right)
        {
            return left.CompareTo(right) == 1;
        }

        public static bool operator ==(Value left, Value right)
        {
            return left.CompareTo(right) == 0;
        }

        public static bool operator !=(Value left, Value right)
        {
            return left.CompareTo(right) != 0;
        }

        public override string ToString()
        {
            return this.valueType.ToString(this.value);
        }
    }

    public class ValueFactory
    {
        private static IDictionary<object, IValueType> _valueTypes =
            new Dictionary<object, IValueType>();

        static ValueFactory()
        {
            _valueTypes.Add(ValueType.String, new StringValueType());
            _valueTypes.Add(ValueType.Integer, new IntegerValueType());
        }

        public static Value Create(object value, object valueType)
        {
            //
            // This logic could be extended to find a ValueType that supports
            // one of the types in the objects inheritance tree. This would
            // also require creating an ObjectValueType, which would be a last
            // resort in the case of the object type not being supported.
            //
            if (!_valueTypes.ContainsKey(valueType))
                throw new ArgumentException("valueType is not supported");

            return new Value(value, _valueTypes[valueType]);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            int x = 32;
            int y = 16;

            Value cx = ValueFactory.Create(x, ValueType.Integer);
            Value cy = ValueFactory.Create(y, ValueType.Integer);

            Console.WriteLine("cx = "+cx);
            Console.WriteLine("cy = "+cy);
            Console.WriteLine("x<y = {0}", cx < cy);
            Console.WriteLine("x>y = {0}", cx > cy);
            Console.WriteLine("x==y = {0}", cx == cy);
            Console.WriteLine("x!=y = {0}", cx != cy);

            Value name = ValueFactory.Create("Jeffrey Schultz", ValueType.String);
            Console.WriteLine("{0} == You = {1}", name, name == "You");

            Console.ReadLine();
        }
    }

答案 4 :(得分:0)

public interface IValueComparer
{
    bool GreaterThan(string source, string destination);
    bool LessThan(string source, string destination);
}

public class IntToIntComparer : IValueComparer
{
    public bool GreaterThan(string source, string detination)
    {
        // better use TryParse and handle exception
        return Int32.Parse(source) > Int32.Parse(detination);
    }

    public bool LessThan(string source, string detination)
    {
        // better use TryParse and handle exception
        return Int32.Parse(source) < Int32.Parse(detination);
    }
}

public class DateToDateComparer : IValueComparer
{
    public bool GreaterThan(string source, string detination)
    {
        // better use TryParse and handle exception
        return DateTime.Parse(source) > DateTime.Parse(detination);
    }

    public bool LessThan(string source, string detination)
    {
        // better use TryParse and handle exception
        return DateTime.Parse(source) < DateTime.Parse(detination);
    }
}

public class StringToStringComparer : IValueComparer
{
    public bool GreaterThan(string source, string detination)
    {
        return source.Length > detination.Length;
    }

    public bool LessThan(string source, string detination)
    {
        return source.Length < detination.Length;
    }
}


public class Condition
{
    public int ID { get; set; }
    public string Value { get; set; }
    public string Type { get; set; }
    public IValueComparer Comparer{get; set;}

    public static string Integer { get { return "Integer"; } }
    public static string String { get { return "String"; } }
    public static string DateTime { get { return "DateTime"; } }

    public static Condition CreateForType(string type)
    {
        if (type == Integer)
            return new Condition { Type = type, Comparer = new IntToIntComparer() };
        if (type == String)
            return new Condition { Type = type, Comparer = new StringToStringComparer() };
        if (type == DateTime)
            return new Condition { Type = type, Comparer = new DateToDateComparer() };
        return null;
    }

    public bool GreaterThan(Condition destination)
    {
        return Comparer.GreaterThan(Value, destination.Value);
    }

    public static bool operator >(Condition source, Condition destination)
    {
        return source.GreaterThan(destination);
    }

    public static bool operator <(Condition source, Condition destination)
    {
        return source.LessThan(destination);
    }

    public bool LessThan(Condition destination)
    {
        return Comparer.LessThan(Value, destination.Value);
    }
}

        var condition1 = Condition.CreateForType("Integer");
        condition1.ID = 1;
        condition1.Value = "5";

        var condition2 = Condition.CreateForType("Integer");
        condition2.ID = 2;
        condition2.Value = "10";

        bool result1 = condition1 > condition2;
        bool result2 = condition1.LessThan(condition2);