获取 属性 类型并将String转换为对应的类型

Get property Type and convert String to corresponding Type

我正在使用 CSOM 更新 Project Server 项目的一些任务。

未定义必须更新的 属性 代码根据字符串形式的 属性 名称动态找出要更新的内容。

为了更好地理解我使用了我的代码的简化版本

//fieldName = "ActualWorkTimeSpan"; value = "16:00:00";
private void Start(string fieldName, string value)
{
    DraftTask draftTask = GetDraftTask();

    Update(draftTask, fieldName, value);

    PublishAndCheckin(draftTask);
}

private static void Update(DraftTask draftTask, string fieldName, string value)
{
    // skip updating if field is Equal
    if (GetPropValue(draftTask, fieldName).ToString() == value)
        return;

    // update of the task
    SetPropValue(draftTask, fieldName, value);

}

private static object GetPropValue(object src, string propName)
{
    return src.GetType().GetProperty(propName).GetValue(src, null);
}

private static void SetPropValue(DraftTask src, string propName, object value)
{
    src.GetType().GetProperty(propName).SetValue(src, value);
}

我可以毫无问题地使用 GetPropValue(),但对于 SetPropValue(),我需要值的类型正确。

在这种情况下,属性 "ActualWorkTimeSpan" 将是 "System.TimeSpan"。所以我需要将字符串“15:00:00”转换为 TimeSpan。

如果每次都是TimeSpan就好办了,不过我可能是Field"Cost"设置更新了

Update(draftTask, "Cost", "500");

所以我的问题是是否可以找出字段的类型并将我的值转换为相同的类型。

您可以使用 Convert.ChangeType 方法做到这一点。

private static void SetPropValue(DraftTask src, string propName, object value)
{
    var property = src.GetType().GetProperty(propName);
    var valueToSet = Convert.ChangeType(value, property.PropertyType);
    property.SetValue(src, valueToSet);
}

ref,在这种情况下是没用的。当您在被调用方法中分配参数并在调用站点(调用方法的范围)分配参数时使用它。

我使用 TypeDescriptor.GetConverter 接受 Type 和 returns 知道如何将 string 转换为指定的 Type TypeConverter ].

然后您可以调用 TypeConverter.ConvertFromString 将字符串转换为所需的 Type

您的代码如下所示:

var propType = src.GetType().GetProperty(propName).PropertyType;
var converter = TypeDescriptor.GetConverter(propType);
var convertedObject = converter.ConvertFromString(src);

最简单的选择是将方法签名更改为通用的或采用 object 类型并实际首先传入正确的数据类型。例如:

private static void Update(DraftTask draftTask, string fieldName, object value)
{
    //snip
}

或通用:

private static void Update<T>(DraftTask draftTask, string fieldName, T value)
{
    //snip
}

现在您可以使用正确的类型调用它,例如:

var timeSpan = new TimeSpan(...);
Update(ref draftTask, "ActualWorkTimeSpan", timeSpan);