C# 如何使用反射为对象上的所有DateTime属性设置DateTime.Kind
在我的应用程序中,我通过web服务检索域对象。在web服务数据中,我知道所有日期值都是UTC,但web服务没有将其C# 如何使用反射为对象上的所有DateTime属性设置DateTime.Kind,c#,datetime,reflection,C#,Datetime,Reflection,在我的应用程序中,我通过web服务检索域对象。在web服务数据中,我知道所有日期值都是UTC,但web服务没有将其xs:dateTime值格式化为UTC日期。(换句话说,字母Z不会附加到每个日期的末尾以表示UTC。) 此时我无法更改web服务的行为方式,但作为一种解决方法,我创建了一个方法,在web服务中的对象被反序列化后立即调用该方法 private void ExplicitlyMarkDateTimesAsUtc<T>(T obj) where T : class
xs:dateTime
值格式化为UTC日期。(换句话说,字母Z
不会附加到每个日期的末尾以表示UTC。)
此时我无法更改web服务的行为方式,但作为一种解决方法,我创建了一个方法,在web服务中的对象被反序列化后立即调用该方法
private void ExplicitlyMarkDateTimesAsUtc<T>(T obj) where T : class
{
Type t = obj.GetType();
// Loop through the properties.
PropertyInfo[] props = t.GetProperties();
for (int i = 0; i < props.Length; i++)
{
PropertyInfo p = props[i];
// If a property is DateTime or DateTime?, set DateTimeKind to DateTimeKind.Utc.
if (p.PropertyType == typeof(DateTime))
{
DateTime date = (DateTime)p.GetValue(obj, null);
date = DateTime.SpecifyKind(date, DateTimeKind.Utc);
p.SetValue(obj, date, null);
}
// Same check for nullable DateTime.
else if (p.PropertyType == typeof(Nullable<DateTime>))
{
DateTime? date = (DateTime?)p.GetValue(obj, null);
DateTime? newDate = DateTime.SpecifyKind(date.Value, DateTimeKind.Utc);
p.SetValue(obj, newDate, null);
}
}
}
private void显式标记日期时间asutc(T obj),其中T:class
{
类型t=obj.GetType();
//循环浏览属性。
PropertyInfo[]props=t.GetProperties();
for(int i=0;i
该方法获取一个对象并循环遍历其属性,查找DateTime
或Nullable
的属性,然后(应该)显式地将每个属性值的DateTime.Kind
属性设置为DateTimeKind.Utc
代码不会抛出任何异常,但是obj
永远不会更改其日期时间属性。在调试器中p.SetValue(obj,date,null)调用了code>,但从未修改过obj
为什么没有将更改应用到obj
?在我尝试时效果很好。注意,你只是在改变种类,而不是时间。如果date.HasValue为false,则不能使用date.Value。确保异常不会被静默捕获并绕过其余的属性分配。修正:
// Same check for nullable DateTime.
else if (p.PropertyType == typeof(Nullable<DateTime>)) {
DateTime? date = (DateTime?)p.GetValue(obj, null);
if (date.HasValue) {
DateTime? newDate = DateTime.SpecifyKind(date.Value, DateTimeKind.Utc);
p.SetValue(obj, newDate, null);
}
}
//对可为空的日期时间进行相同的检查。
else if(p.PropertyType==typeof(可空)){
DateTime?date=(DateTime?)p.GetValue(obj,null);
if(date.HasValue){
DateTime?newDate=DateTime.SpecifyKind(date.Value,DateTimeKind.Utc);
p、 设置值(obj,newDate,null);
}
}
有关博客帖子,请参阅。我使用以下代码将WCF响应对象图转换为所有本地时间:
/// <summary>
/// Since all dates in the DB are stored as UTC, this converts dates to the local time using the Windows time zone settings.
/// </summary>
public static class AllDateTimesAsUTC
{
/// <summary>
/// Specifies that an object's dates are coming in as UTC.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static T AllDatesAreUTC<T>(this T obj)
{
if (obj == null)
{
return default(T);
}
IterateDateTimeProperties(obj);
return obj;
}
private static void IterateDateTimeProperties(object obj)
{
if (obj == null)
{
return;
}
var properties = obj.GetType().GetProperties();
//Set all DaetTimeKinds to Utc
foreach (var prop in properties)
{
var t = prop.PropertyType;
if (t == typeof(DateTime) || t == typeof(DateTime?))
{
SpecifyUtcKind(prop, obj);
}
else if (t.IsEnumerable())
{
var vals = prop.GetValue(obj, null);
if (vals != null)
{
foreach (object o in (IEnumerable)vals)
{
IterateDateTimeProperties(o);
}
}
}
else
{
var val = prop.GetValue(obj, null);
if (val != null)
{
IterateDateTimeProperties(val);
}
}
}
//properties.ForEach(property => SpecifyUtcKind(property, obj));
return; // obj;
}
private static void SpecifyUtcKind(PropertyInfo property, object value)
{
//Get the datetime value
var datetime = property.GetValue(value, null);
DateTime output;
//set DateTimeKind to Utc
if (property.PropertyType == typeof(DateTime))
{
output = DateTime.SpecifyKind((DateTime)datetime, DateTimeKind.Utc);
}
else if (property.PropertyType == typeof(DateTime?))
{
var nullable = (DateTime?)datetime;
if (!nullable.HasValue) return;
output = (DateTime)DateTime.SpecifyKind(nullable.Value, DateTimeKind.Utc);
}
else
{
return;
}
Debug.WriteLine(" ***** Converted date from {0} to {1}.", datetime, output);
datetime = output.ToLocalTime();
//And set the Utc DateTime value
property.SetValue(value, datetime, null);
}
internal static Type[] ConvertibleTypes = {typeof(bool), typeof(byte), typeof(char),
typeof(DateTime), typeof(decimal), typeof(double), typeof(float), typeof(int),
typeof(long), typeof(sbyte), typeof(short), typeof(string), typeof(uint),
typeof(ulong), typeof(ushort)};
/// <summary>
/// Returns true if this Type matches any of a set of Types.
/// </summary>
/// <param name="types">The Types to compare this Type to.</param>
public static bool In(this Type type, params Type[] types)
{
foreach (Type t in types) if (t.IsAssignableFrom(type)) return true; return false;
}
/// <summary>
/// Returns true if this Type is one of the types accepted by Convert.ToString()
/// (other than object).
/// </summary>
public static bool IsConvertible(this Type t) { return t.In(ConvertibleTypes); }
/// <summary>
/// Gets whether this type is enumerable.
/// </summary>
public static bool IsEnumerable(this Type t)
{
return typeof(IEnumerable).IsAssignableFrom(t);
}
/// <summary>
/// Returns true if this property's getter is public, has no arguments, and has no
/// generic type parameters.
/// </summary>
public static bool SimpleGetter(this PropertyInfo info)
{
MethodInfo method = info.GetGetMethod(false);
return method != null && method.GetParameters().Length == 0 &&
method.GetGenericArguments().Length == 0;
}
}
//
///由于数据库中的所有日期都存储为UTC,因此会使用Windows时区设置将日期转换为本地时间。
///
公共静态类AllDateTimesAsUTC
{
///
///指定对象的日期以UTC的形式输入。
///
///
///
///
公共静态T AllDatesAreUTC(此T obj)
{
if(obj==null)
{
返回默认值(T);
}
迭代时间属性(obj);
返回obj;
}
私有静态void IterateDateTimeProperties(对象obj)
{
if(obj==null)
{
返回;
}
var properties=obj.GetType().GetProperties();
//将所有DaetTimeKinds设置为Utc
foreach(属性中的var属性)
{
var t=prop.PropertyType;
如果(t==typeof(DateTime)| t==typeof(DateTime?)
{
指定类别(道具、obj);
}
else if(t.IsEnumerable())
{
var VAL=prop.GetValue(对象,空);
如果(VAL!=null)
{
foreach(对象o在(IEnumerable)VAL中)
{
迭代时间属性(o);
}
}
}
其他的
{
var val=prop.GetValue(对象,空);
如果(val!=null)
{
IterateDateTimeProperties(val);
}
}
}
//ForEach(property=>SpecifyUtcKind(property,obj));
return;//obj;
}
私有静态void SpecifyUtcKind(PropertyInfo属性,对象值)
{
//获取日期时间值
var datetime=property.GetValue(值,null);
日期时间输出;
//将DateTimeKind设置为Utc
if(property.PropertyType==typeof(DateTime))
{
输出=DateTime.SpecifyKind((DateTime)DateTime,DateTimeKind.Utc);
}
else if(property.PropertyType==typeof(DateTime?)
{
var nullable=(DateTime?)DateTime;
如果(!nullable.HasValue)返回;
输出=(DateTime)DateTime.SpecifyKind(nullable.Value,DateTimeKind.Utc);
}
其他的
{
返回;
}
WriteLine(“******将日期从{0}转换为{1}.”,datetime,output);
datetime=output.ToLocalTime();
//并设置Utc日期时间值
SetValue(值,日期时间,null);
}
内部静态类型[]可转换类型={typeof(bool)、typeof(byte)、typeof(char),
typeof(日期时间)、typeof(十进制)、typeof(双精度)、typeof(浮点)、typeof(整数),
typeof(长)、typeof(短)、typeof(短)、typeof(字符串)、typeof(uint),
typeof(ulong),typeof(ushort)};
///
///如果此类型与一组类型中的任何一个匹配,则返回true。
///
///要将此类型与之进行比较的类型。
公共静态布尔输入(此类型,参数
void svc_ZOut_GetZOutSummaryCompleted(object sender, ZOut_GetZOutSummaryCompletedEventArgs e)
{
svc.ZOut_GetZOutSummaryCompleted -= new EventHandler<ZOut_GetZOutSummaryCompletedEventArgs>(svc_ZOut_GetZOutSummaryCompleted);
svc = null;
var whenDone = (Action<bool, ZOutResult>)e.UserState;
if (e.Error != null)
{
FireOnExceptionRaised(e.Error);
whenDone(false, null);
}
else
{
var res = e.Result.AllDatesAreUTC();
FireOnSessionReceived(res.IsError, res.Session);
if (res.IsError == true)
{
whenDone(false, null);
}
else
{
whenDone(true, res.Result);
}
}
}
// Same check for nullable DateTime.
else if (p.PropertyType == typeof(Nullable<DateTime>)) {
DateTime? date = (DateTime?)p.GetValue(obj, null);
if (date.HasValue) {
DateTime? newDate = DateTime.SpecifyKind(date.Value, DateTimeKind.Utc);
p.SetValue(obj, null, null);
p.SetValue(obj, newDate, null);
}
}
public static void ConvertDatesToUtc(this object obj) {
foreach (var prop in obj.GetType().GetProperties().Where(p => p.CanWrite)) {
var t = prop.PropertyType;
if (t == typeof(DateTime)) {
//found datetime, specify its kind as utc.
var oldValue = (DateTime)prop.GetValue(obj, null);
var newValue = DateTime.SpecifyKind(oldValue, DateTimeKind.Utc);
prop.SetValue(obj, newValue, null);
} else if (t == typeof(DateTime?)) {
//found nullable datetime, if populated specify its kind as utc.
var oldValue = (DateTime?)prop.GetValue(obj, null);
if (oldValue.HasValue) {
var newValue = (DateTime)DateTime.SpecifyKind(oldValue.Value, DateTimeKind.Utc);
prop.SetValue(obj, newValue, null);
}
} else if (typeof(IEnumerable).IsAssignableFrom(t)) {
//traverse child lists recursively.
var vals = prop.GetValue(obj, null);
if (vals != null) {
foreach (object o in (IEnumerable)vals) {
ConvertDatesToUtc(o);
}
}
} else {
//traverse child objects recursively.
var val = prop.GetValue(obj, null);
if (val != null)
ConvertDatesToUtc(val);
}
}
}