【问题标题】:Convert and Return generic value from database从数据库转换并返回通用值
【发布时间】:2014-03-19 22:38:33
【问题描述】:

我想从数据库中返回值。 我定义了表,其中每列都定义了数据类型:

public enum TTableOffers
{
    [CStringValue("id")]
    [CType(typeof(Integer))]
    Id = 0,
    [CStringValue("project")]
    [CType(typeof(String))]
    ProjectId = 1,

}

所以列“id”是整数类型,“项目”是字符串等。 现在我想通过这个枚举从特定列中获取值,如下所示:

    public T Value<T>(Enum enumColumn) where T : class // <<< class!
    {
        object aResult = m_aSqlDataReader.GetValue(columnIndex); // Here the aResult is filled with correct value (object) from database (working fine)

        ...     

        Type colType = CTypeAttribute.GetTypeValue(enumColumn); // Read the type from table - Integer or String (this is working fine)

        if (aResult == null) 
            return default(T);
        else
        {
           if (Convert.IsDBNull(aResult))
              return default(T);
           else
              aResult = ChangeType(aResult, colType); // Change the type to desired one --- here is the crash!!!                             
        }

        return (T)aResult;
       // here I also tried: return aResult as T;
    }

作为方法ChangeType我用这个:Invalid cast from 'System.Int32' to 'System.Nullable`1[[System.Int32, mscorlib]]

String 类型的列工作正常,但 Integer 存在问题。

因为我不能使用 Int32(它是 struct),所以我定义了自己的 Integer 类,如下所示:

public class Integer : IComparable, IFormattable, IConvertible, IComparable<Integer>, IEquatable<Integer>
{
    int value = 0;

    public Integer(int value)
    {
        this.value = value;
    }

    // (Integer)123
    public static implicit operator Integer(int value)
    {
        return new Integer(value);
    }

    // (int)myInteger
    public static implicit operator int(Integer integer)
    {
        if (integer == null)
            integer = new Integer(default(int));

        return integer.value;
    }

    public static int operator +(Integer one, Integer two)
    {
        return one.value + two.value;
    }

    public static Integer operator +(int one, Integer two)
    {
        return new Integer(one + two);
    }

    public static int operator -(Integer one, Integer two)
    {
        return one.value - two.value;
    }

    public static Integer operator -(int one, Integer two)
    {
        return new Integer(one - two);
    }

    public static bool operator >(Integer one, int two)
    {
        return (int)one > two;
    }

    public static bool operator <(Integer one, int two)
    {
        return (int)one < two;
    }

    public static bool operator >(int one, Integer two)
    {
        return one > (int)two;
    }

    public static bool operator <(int one, Integer two)
    {
        return one < (int)two;
    }

    public TypeCode GetTypeCode()
    {
        throw new NotImplementedException();
    }

    public bool ToBoolean(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public byte ToByte(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public char ToChar(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public DateTime ToDateTime(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public decimal ToDecimal(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public double ToDouble(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public short ToInt16(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public int ToInt32(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public long ToInt64(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public sbyte ToSByte(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public float ToSingle(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public string ToString(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public object ToType(Type conversionType, IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public ushort ToUInt16(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public uint ToUInt32(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public ulong ToUInt64(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }

    public int CompareTo(object obj)
    {
        throw new NotImplementedException();
    }

    public string ToString(string format, IFormatProvider formatProvider)
    {
        throw new NotImplementedException();
    }

    public int CompareTo(Integer other)
    {
        throw new NotImplementedException();
    }

    public bool Equals(Integer other)
    {
        throw new NotImplementedException();
    }
}

对于 String,一切正常,但对于 Integer,我得到 "Invalid cast from 'System.Int32' to 'Code.Data.Integer'。" 异常。

我在 Integer 类的每一行都设置了断点,没有人被击中。我假设我在 Integer 类中遗漏了一些重要的东西,因为它永远不会被击中并且没有完成转换。

我错过了什么?

【问题讨论】:

  • 我认为在这种情况下使用属性是个坏主意,就返回类型而言。如果您正确地使用通用方法,那么它自己的签名将已经为您提供输入信息。无需在每次调用中对您已经知道的内容进行反思。 :)

标签: c#


【解决方案1】:

您的问题是您的值(在本例中为 int)没有实现 IConvertible 接口。来自MSDNdocumentation

ChangeType 是一种通用的转换方法,可将 由转换类型的值指定的对象。 value参数可以 可以是任意类型的对象,conversionType 也可以是 Type 对象 表示任何基本类型或自定义类型。 转换为 成功,value 必须实现 IConvertible 接口,因为 方法只是包装对适当 IConvertible 方法的调用。这 方法要求将 value 转换为 conversionType 支持。

另外,来自IConvertible 上的文档:

如果您实现 IConvertible 接口,您的实现将 如果 Object 则由 Convert.ChangeType 方法自动调用 参数是您的实现类型和类型的实例 参数是公共语言运行时类型。

您以相反的方式调用它:从 CLR 类型 (int) 转换为您的自定义类型,这是行不通的。

【讨论】:

  • 你可能是对的,我无法解决它,所以我为每种类型创建了单独的方法,谢谢。
【解决方案2】:

你为什么不做两个这样的 Value 方法:

public Nullable<T> Value<T>(Enum enumColumn) where T : struct {...}

public string Value(Enum enumColumn) {...}

第一个允许您返回空整数。

干净多了,不是吗? :)

【讨论】:

  • 我最后为每种类型创建了单独的方法,例如 .GetString(Enum enumColumn) .GetInt(Enum enumColumn), GetDateTime(... ,但无论如何谢谢。
  • 没问题。 :) 出于好奇,您在使用 Nullable 结构类型方法时遇到过任何问题吗?我自己已经使用它几年了,它对我来说完美无缺。它在一个地方支持十进制、short、int、datetime、long、guid、float 和 char。我必须做的唯一例外是字符串。
猜你喜欢
  • 2013-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多