在F#中使用System.Reflection分配属性值

Jam*_*xon 3 f#

我在C#中具有以下代码行:

internal static object AssignMatchingPropertyValues(object sourceObject, object targetObject)
{
    Type sourceType = sourceObject.GetType();
    PropertyInfo[] sourcePropertyInfos = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
    foreach (var sourcePropertyInfo in sourcePropertyInfos)
    {
        var targetPropertyInfo = targetObject.GetType().GetProperty(sourcePropertyInfo.Name);
        if (targetPropertyInfo != null)
        {
            targetPropertyInfo.SetValue(targetObject, sourcePropertyInfo.GetValue(sourceObject, null), null);
        }
    }
    return targetObject;
}
Run Code Online (Sandbox Code Playgroud)

我想在F#中实现等效功能,因此我做了如下操作:

member this.AssignMatchingPropertyValues(sourceObject, targetObject)=
    let sourceType = sourceObject.GetType()
    let sourcePropertyInfos = sourceType.GetProperties(BindingFlags.Instance)
    let assignedProperities = sourcePropertyInfos 
                                |> Seq.map(fun spi -> spi, targetObject.GetType().GetProperty(spi.Name))
                                |> Seq.map(fun (spi,tpi) -> tpi.SetValue(targetObject, spi.GetValue(sourceObject,null),null))        
    ()
Run Code Online (Sandbox Code Playgroud)

问题是它不起作用。我认为不变性是永恒的,我正在得到一个新系列。有没有办法引用原始收藏?这是解决这个问题的正确途径吗?

Lee*_*Lee 5

Seq.map很懒,您没有在任何地方进行评估。您可以使用Seq.iter

sourcePropertyInfos 
    |> Seq.map(fun spi -> spi, targetObject.GetType().GetProperty(spi.Name))
    |> Seq.iter(fun (spi,tpi) -> tpi.SetValue(targetObject, spi.GetValue(sourceObject,null),null))
Run Code Online (Sandbox Code Playgroud)


Dan*_*iel 5

这是C#的直接翻译,而不是F#代码:

let AssignMatchingPropertyValues sourceObject targetObject =
    let sourceType = sourceObject.GetType()
    let targetType = targetObject.GetType()
    let sourcePropertyInfos = sourceType.GetProperties(BindingFlags.Public ||| BindingFlags.Instance)
    for sourcePropertyInfo in sourcePropertyInfos do
        match targetType.GetProperty(sourcePropertyInfo.Name) with
        | null -> ()
        | targetPropertyInfo -> targetPropertyInfo.SetValue(targetObject, sourcePropertyInfo.GetValue(sourceObject, null), null)
    targetObject
Run Code Online (Sandbox Code Playgroud)