如何将属性作为参数传递,以便使用同一个函数修改不同的属性

本文关键字:属性 函数 同一个 修改 参数传递 | 更新日期: 2023-09-27 18:06:36

我发现以前问过类似的问题,但我看到的答案是特定于该人给出的示例或针对该人示例的变通方法,而不是一般解决方案。

我想把一个类的属性传递给一个函数来对这个属性进行操作。我要使用的例子是递增一个值,但我有更复杂的场景,所以我正在寻找一个通用的解决方案,而不是一个具体递增的答案。

我过去是怎么做的,我要么有多个功能IncrementPassengerCount, IncrementDistanceTravelled, IncrementPlaneAge,但这是不方便和可怕的。

我想要一个通用的函数,我可以用下面的伪代码来调用:

Increment(myPlane, myPlane.DistanceTravelled);
Increment(myPlane, myPlane.PlaneAge);
//where
public void Increment(Airplane myPlane, Property propToIncrement)
{
     myPlane.propToIncrement++; //or do whatever like I now have myPlane.DistanceTravelled
}

我试过了:

Increment(myPlane, x => x.DistanceTravelled);
//where
public void Increment(Airplane myPlane, Func<Log, IComparable> property)
{
     property(myPlane)++;
}

但是这会导致

操作符'++'不能应用于'System '类型的操作数。IComparable '

有办法做我想象的还是我看错了?

如何将属性作为参数传递,以便使用同一个函数修改不同的属性

这是可能的,虽然很复杂,可能是您应该用另一种方式来做的标志,但这里就是这样。(正如Jon Skeet提到的,我建议只使用++操作符,而不是调用Increment方法。除了这个方法,我还包含了两个类,它们将允许你在控制台应用中测试代码。这需要大量的错误检查。我有几个空支票,但可能有更多的地方需要它。如果重载了++操作符,它也适用于这些类型,但不能预见任何错误。

public static void Increment(this object o, string propertyName)  
    {
        var property = o.GetType().GetProperty(propertyName);
        if (property == null)
            return;
        var val = property.GetValue(o, null);
        var op_Inc = o.GetType().GetMethod("op_Increment");
        if(op_Inc != null)
        {
            var val2 = op_Inc.Invoke(val, null);
            property.SetValue(o,val2);
        }
        switch (Type.GetTypeCode(property.PropertyType))
        {
            case TypeCode.UInt16:
            {
                var x = (UInt16)val;
                x++;
                property.SetValue(o, x);
            }
                break;
            case TypeCode.UInt32:
                {
                    var x = (UInt32)val;
                    x++;
                    property.SetValue(o, x);
                }
                break;
            case TypeCode.UInt64:
                {
                    var x = (UInt64)val;
                    x++;
                    property.SetValue(o, x);
                }
                break;
            case TypeCode.Int16:
                {
                    var x = (Int16)val;
                    x++;
                    property.SetValue(o, x);
                }
                break;
            case TypeCode.Int32:
                {
                    var x = (Int32)val;
                    x++;
                    property.SetValue(o, x);
                }
                break;
            case TypeCode.Int64:
                {
                    var x = (Int64)val;
                    x++;
                    property.SetValue(o, x);
                }
                break;
            case TypeCode.Decimal:
                {
                    var x = (Decimal)val;
                    x++;
                    property.SetValue(o, x);
                }
                break;
            case TypeCode.Double:
                {
                    var x = (Double)val;
                    x++;
                    property.SetValue(o, x);
                }
                break;
            case TypeCode.Single:
                {
                    var x = (Single)val;
                    x++;
                    property.SetValue(o, x);
                }
                break;
        }

    }
}
public class Example
{
    public static void Main()
    {
        var plane = new Plane(){DistanceTravelled = 0, PlaneAge = 0};
        Console.WriteLine("Before invoking increment: dist = {0}, age = {1}", plane.DistanceTravelled, plane.PlaneAge);
        plane.Increment("DistanceTravelled");
        plane.Increment("PlaneAge");
        Console.WriteLine("After invoking increment: dist = {0}, age = {1}", plane.DistanceTravelled, plane.PlaneAge);
        Console.ReadKey();
    }

}
public class Plane
{
    public int DistanceTravelled { get; set; }
    public int PlaneAge { get; set; }
}