【问题标题】:Get property Type and convert String to corresponding Type获取属性Type并将String转换为对应的Type
【发布时间】:2017-11-16 13:35:54
【问题描述】:

我正在使用 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 会很容易做到,但我可能是“成本”字段设置为更新。

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

所以我的问题是是否有可能找出该字段的类型,然后将我的值转换为相同的类型。

【问题讨论】:

  • 为什么需要它的类型正确? SetValue 无论如何都采用 object 类型。
  • 另外,我认为您不了解 ref 关键字的作用,我建议您也阅读一下。
  • 一开始你的所有数据都是字符串的原因是什么?
  • 您能否澄清一下您是要解析字符串值还是其他方式?另外,为什么要使用反射?
  • @RandRandom - 你是完全正确的。但是,如果 OP 可以做到这一点,他们真的不应该使用反射。我只能假设字段名在下拉列表或配置文件中,Update(ref draftTask, "ActualWorkTimeSpan", "15:00:00"); 只是一个示例

标签: c# csom


【解决方案1】:

我使用TypeDescriptor.GetConverter,它接受Type 并返回一个TypeConverter,它知道如何将string 转换为指定的Type

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

您的代码如下所示:

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

【讨论】:

  • 这当然可以,但它实际上只是掩盖了方法签名一开始就错误的事实。
【解决方案2】:

最简单的选择是将方法签名更改为泛型或采用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);

【讨论】:

    【解决方案3】:

    您可以通过使用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,在这种情况下是没有用的。当您在被调用方法中分配参数并在调用站点(调用方法的范围)也分配参数时使用它。

    【讨论】:

    • and assign new object to that object 应该是and assign new object to that reference
    猜你喜欢
    • 2012-04-04
    • 2015-09-24
    • 2017-06-05
    • 2014-03-12
    • 2020-07-05
    • 2020-04-23
    • 2020-12-27
    • 2013-11-03
    • 1970-01-01
    相关资源
    最近更新 更多