【问题标题】:C# how to set parameter value by Func DelegateC#如何通过Func Delegate设置参数值
【发布时间】:2020-05-14 17:56:43
【问题描述】:

我需要一种干净的方法来使用同一类的参数更新对象。 我将字段列表定义为Func<T, object> 代表。这些是需要比较和更新的列表。不幸的是,我想不出一个干净的方法来实现它。

以下代码不起作用:

public class UpdatableClass
{
    public int Id { get; set; }
    public int IntValue { get; set; }
    public string StringValue { get; set; }
    public DateTime ModifiedDate { get; set; }


    private List<Func<UpdatableClass, object>> UpdatableFields =
        new List<Func<UpdatableClass, object>>()
        {
            c => c.IntValue,
            c => c.StringValue
        };

    public bool Update(UpdatableClass newValues)
    {
        bool isUpdated = false;
        foreach (var fieldSelector in UpdatableFields)
        {
            object oldValue = fieldSelector(this);
            object newValue = fieldSelector(newValues);
            if (!newValue.Equals(oldValue))
            {
                oldValue = newValue;
                isUpdated = true;
            }
        }

        return isUpdated;
    }
}

[TestFixture]
public class UpdatableClassTests
{
    [Test]
    public void TestUpdateMethod()
    {
        UpdatableClass oldObject = new UpdatableClass()
        {
            StringValue = "OldString",
            IntValue = 3,
        };

        bool isUpdated = oldObject.Update(new UpdatableClass() { StringValue = "NewString", IntValue = 4 });

        Assert.IsTrue(isUpdated);
        Assert.AreEqual("NewString", oldObject.StringValue);
        Assert.AreEqual(4, oldObject.IntValue);
    }
}

【问题讨论】:

  • 你最好使用像 AutoMapper 这样的库来为你做这件事。
  • You Func&lt;UpdatableClass, object&gt; 只返回值,然后您将其用于比较。您需要定义一个 Action 来设置属性的值。或者写类似thread
  • 最好的单元测试是在你运行它之前就失败的那个。很难看出这段代码的意义。
  • @HansPassant,您能详细说明一下吗?我想成为一个更好的提问者:)

标签: c#


【解决方案1】:

此代码可用作问题的可能解决方案。除了只获取Func&lt;T, object&gt;,您还可以对getter 和setter (Func&lt;UpdatableClass, object&gt; Get, Action&lt;UpdatableClass, object&gt; Set) 使用一个元组。我不认为这是最好的解决方案,但它可以解决问题并通过测试

public class UpdatableClass
{
    public int Id { get; set; }
    public int IntValue { get; set; }
    public string StringValue { get; set; }
    public DateTime ModifiedDate { get; set; }

    private List<(Func<UpdatableClass, object> Get, Action<UpdatableClass, object> Set)> UpdatableFields =
        new List<(Func<UpdatableClass, object>, Action<UpdatableClass, object>)>
        {
            (c => c.IntValue, (c, v) => { c.IntValue = Convert.ToInt32(v); }),
            (c => c.StringValue, (c, v) => { c.StringValue = v.ToString(); })
        };

    public bool Update(UpdatableClass newValues)
    {
        bool isUpdated = false;
        foreach (var field in UpdatableFields)
        {
            object oldValue = field.Get(this);
            object newValue = field.Get(newValues);
            if (!newValue.Equals(oldValue))
            {
                field.Set(this, newValue);
                isUpdated = true;
            }
        }

        return isUpdated;
    }
}   

【讨论】:

  • 谢谢!它绝对比一个一个地显式检查每个参数要好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多