指向没有反射或数据绑定的属性

时间:2017-07-20 17:18:40

标签: c# pointers reflection

我想创建一个具有"变量"的属性的类。指向另一个类中的其他属性。

想象一个具有几个整数属性(Limit1,Limit2等)的类(称为" Limiter")。

我现在想要第二堂课(" LimitWatcher"),它可以"观看"其中一个限制。但是我希望能够在构造函数中设置它正在观察的特定限制。我最终想要几个LimitWatcher实例,每个实例都指向一个单独的Limit。在Watchers实例化之后,Limit值本身可能会发生变化,但观察者必须始终看到它正在观看的Limit的当前值。基本上,我想存储对整数的引用。

我知道我可以使用反射来实现这一点(参见下面的示例),但我觉得可能有一种更简单的方法。

using System;
namespace ConsoleApplication4
{
    public class Limiter 
    {
        public int limit1 { get; set; } = 10;
        public int limit2 { get; set; } = 20;
        public void Update()
        {
            limit1++;
            limit2++;
        }
    }
    public class LimitWatcher
    {
        public LimitWatcher(Limiter lim, string propName)
        {
            myLimiter = lim;
            limitName = propName;
        }
        private Limiter myLimiter { get; }
        public string limitName { get; set; }
        //can I do this without reflection:
        public int FooLimit { get { return (int)typeof(Limiter).GetProperty(limitName).GetValue(myLimiter); } }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Limiter lim = new ConsoleApplication4.Limiter();
            LimitWatcher w1 = new LimitWatcher(lim, nameof(lim.limit1));
            LimitWatcher w2 = new LimitWatcher(lim, nameof(lim.limit2));
            lim.Update();
            Console.WriteLine($"1st watcher sees {w1.FooLimit}");  //11
            Console.WriteLine($"2nd watcher sees {w2.FooLimit}"); //21
            Console.ReadKey();
        }
    }
}

2 个答案:

答案 0 :(得分:2)

你可以在构造函数中使用Func,类似于:

private Limiter limiter;
private Func<Limiter, int> propertyAccesor;

public LimitWatcher(Limiter lim, string propName, Func<Limiter, int> propertyAccesor)
{
    this.propertyAccesor = propertyAccesor;
}

public bool LimitExceeded()
{
     int propertyValue = propertyAccesor(limiter);
     return propertyValue > 20;
}

答案 1 :(得分:1)

您可以使用动态表达式:

using System.Linq.Expressions;

public class LimitWatcher
{
    public LimitWatcher(Limiter lim, string propName)
    {
        myLimiter = lim;
        limitName = propName;

        var parameter = Expression.Parameter(typeof(Limiter), "x");
        var member = Expression.Property(parameter, propName);
        var finalExpression = Expression.Lambda<Func<Limiter, int>>(member, parameter);
        getter = finalExpression.Compile();
    }

    private Func<Limiter, int> getter;

    private Limiter myLimiter { get; }
    public string limitName { get; set; }

    public int FooLimit { get { return getter(myLimiter); } }
}

受此article启发