使用反射设置时,C#DateTime返回默认值

时间:2015-02-19 18:38:37

标签: c# .net datetime reflection

我在一个类中有一个静态方法,它在运行时设置一个对象,如下所述:http://benohead.com/create-anonymous-types-at-runtime-in-c-sharp/

对于新创建的对象,我添加了从发送到我的方法的不同对象组合的属性,并在反射中设置值并返回新创建的对象。所有值似乎都有值(到目前为止我测试了字符串和整数) - 但值都在那里。

问题是当我将DateTime值设置为DateTime属性时 - 返回的值是01/01/0001而不是我设置的日期。

以下是在反射中设置值的代码:

foreach (string key in values.Keys)
{
    if (sqlParams == null || sqlParams.Contains(key))
    {
        PropertyValue propertyValue = values[key];
        object val = propertyValue.Value;
        if (val == null)
            val = getDefaultValue(propertyValue.PropertyType);
         else if (propertyValue.PropertyType == typeof(DateTime) && (DateTime)propertyValue.Value == DateTime.MinValue)
            val = new DateTime(1982, 5, 6);// (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue;
         myType.GetProperty(key).SetValue(obj, val);
    }
}

为什么没有正确返回DateTime值?

修改

完整的代码:

    private static object createDummyObject(Dictionary<string, PropertyValue> values, List<string> sqlParams)
    {
        // Code for creating .NET objects at runtime thanks to:
        // http://benohead.com/create-anonymous-types-at-runtime-in-c-sharp/

        AssemblyBuilder dynamicAssembly =
            AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Poco.Sql.Assembly"),
            AssemblyBuilderAccess.Run);

        ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule("Poco.Sql.Module");
        TypeBuilder dynamicType = dynamicModule.DefineType("Poco.Sql.DynamicType", TypeAttributes.Public);

        foreach(string key in values.Keys)
        {
            if (sqlParams == null || sqlParams.Contains(key))
            {
                PropertyValue propertyValue = values[key];
                addProperty(dynamicType, key, propertyValue.PropertyType);
            }
        }

        Type myType = dynamicType.CreateType();
        object obj = Activator.CreateInstance(myType);

        foreach (string key in values.Keys)
        {
            if (sqlParams == null || sqlParams.Contains(key))
            {
                PropertyValue propertyValue = values[key];
                object val = propertyValue.Value;
                if (val == null)
                    val = getDefaultValue(propertyValue.PropertyType);
                else if (propertyValue.PropertyType == typeof(DateTime) && (DateTime)propertyValue.Value == DateTime.MinValue)
                    val = new DateTime(1982, 5, 6);// (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue;
                myType.GetProperty(key).SetValue(obj, val);
            }
        }

        return obj;
    }

    private static void addProperty(TypeBuilder typeBuilder, string propertyName, Type propertyType)
    {
        const MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.HideBySig;

        FieldBuilder field = typeBuilder.DefineField("_" + propertyName, typeof(string), FieldAttributes.Private);
        PropertyBuilder property = typeBuilder.DefineProperty(propertyName, System.Reflection.PropertyAttributes.None, propertyType, new[] { propertyType });

        MethodBuilder getMethodBuilder = typeBuilder.DefineMethod("get_value", getSetAttr, propertyType, Type.EmptyTypes);
        ILGenerator getIl = getMethodBuilder.GetILGenerator();
        getIl.Emit(OpCodes.Ldarg_0);
        getIl.Emit(OpCodes.Ldfld, field);
        getIl.Emit(OpCodes.Ret);

        MethodBuilder setMethodBuilder = typeBuilder.DefineMethod("set_value", getSetAttr, null, new[] { propertyType });
        ILGenerator setIl = setMethodBuilder.GetILGenerator();
        setIl.Emit(OpCodes.Ldarg_0);
        setIl.Emit(OpCodes.Ldarg_1);
        setIl.Emit(OpCodes.Stfld, field);
        setIl.Emit(OpCodes.Ret);

        property.SetGetMethod(getMethodBuilder);
        property.SetSetMethod(setMethodBuilder);
    }

    private static object getDefaultValue(Type t)
    {
        if (t == typeof(DateTime))
            return DateTime.MinValue;
        else if (t.IsValueType)
            return Activator.CreateInstance(t);

        return null;
    }

以及上面代码中使用的PropertyValue类:

class PropertyValue
{
    public object Value { get; set; }
    public Type PropertyType { get; set; }
}

1 个答案:

答案 0 :(得分:0)

问题可能在这里?

private static object getDefaultValue(Type t)
    {
        if (t == typeof(DateTime))
            return DateTime.MinValue;
        else if (t.IsValueType)
            return Activator.CreateInstance(t);

        return null;
    }

日期存储为64位带符号的整数,表示从01/01/0001 12:00开始的“滴答”数(1滴= 100纳秒)。当您致电DateTime.MinValue时,输出为01/01/0001。