【问题标题】:How to store reference to Class' property and access an instance's property by that? [closed]如何存储对类属性的引用并通过它访问实例的属性? [关闭]
【发布时间】:2013-06-07 09:25:46
【问题描述】:

我如何保留到类属性的某种链接,然后使用它来访问实例的属性?问题是没有创建链接的类实例。这个想法是在可以访问任何实例之前记住该属性。

这是一个例子:

Class A { int integer { get; set; }  }

var link = GetLink(A.integer); // implementetion of GetLink(???) is unknown

MyMethod(link);

void MyMethod(??? link)
{
    A a = new A();
    int i = GetValueByLink(a, link); // this is also undefined
}

有没有办法在 C# 中做这样的事情?

【问题讨论】:

    标签: c# properties reference


    【解决方案1】:

    您可以编写一个使用反射的属性包装类,如下所示:

    public class PropertyWrapper<T>
    {
        readonly PropertyInfo property;
        readonly object obj;
    
        public PropertyWrapper(object obj, string propertyName)
        {
            property = obj.GetType().GetProperty(propertyName);
            this.obj = obj;
        }
    
        public T Value
        {
            get
            {
                return (T)property.GetValue(obj);
            }
    
            set
            {
                property.SetValue(obj, value);
            }
        }
    }
    

    然后你可以像这样使用它:

    public class Test
    {
        public string Item { get; set; }
    }
    
    class Program
    {
        void run()
        {
            Test test = new Test { Item = "Initial Item" };
    
            Console.WriteLine(test.Item); // Prints "Initial Item"
    
            var wrapper = new PropertyWrapper<string>(test, "Item");
    
            Console.WriteLine(wrapper.Value); // Prints "Initial Item"
    
            wrapper.Value = "Changed Item";
    
            Console.WriteLine(wrapper.Value); // Prints "Changed Item"
        }
    
        static void Main()
        {
            new Program().run();
        }
    }
    

    [编辑] 我不得不回到这里发布一种无需反思的方式:

    public class PropertyWrapper<T>
    {
        readonly Action<T> set;
        readonly Func<T>   get;
    
        public PropertyWrapper(Func<T> get, Action<T> set)
        {
            this.get = get;
            this.set = set;
        }
    
        public T Value
        {
            get
            {
                return get();
            }
    
            set
            {
                set(value);
            }
        }
    }
    
    public class Test
    {
        public string Item
        {
            get;
            set;
        }
    }
    
    class Program
    {
        void run()
        {
            Test test = new Test
            {
                Item = "Initial Item"
            };
    
            Console.WriteLine(test.Item); // Prints "Initial Item"
    
            var wrapper = new PropertyWrapper<string>(() => test.Item, value => test.Item = value);
    
            Console.WriteLine(wrapper.Value); // Prints "Initial Item"
    
            wrapper.Value = "Changed Item";
    
            Console.WriteLine(wrapper.Value); // Prints "Changed Item"
        }
    
        static void Main()
        {
            new Program().run();
        }
    }
    

    【讨论】:

    • 我的意图并没有那么远,但这看起来仍然非常有用。
    • @user1306322 我添加了一种使用 lambdas 而不是反射的方法。 ;)
    【解决方案2】:

    您似乎在寻找Reflection

    例子:

    public class A
    {
      int integer{get; set;}
    }
    
    PropertyInfo prop = typeof(A).GetProperty("integer");
    A a = new A();
    prop.GetValue(a, null);
    prop.SetValue(a, 1234, null);
    

    您仍然需要引用 set/get 值,但这似乎是您想要的。

    【讨论】:

    • 谢谢,这正是我想要的!
    【解决方案3】:

    如果一个属性是一个引用类型 - 你只需要保留一个对实例的引用。然后您可以更改/修改该实例的公共属性/字段(或调用方法)。

    如果属性是值类型,或者如果您需要更改引用本身(使其指向新实例) - 唯一与您所描述的内容相近的事情涉及

    PropertyInfo property = obj.GetType().GetProperty(<property name>);
    

    object value = property.GetValue(obj, null);
    property.SetValue(obj, newValue, null);
    

    您仍然需要对要获取/设置其属性的实例的引用。

    【讨论】:

      【解决方案4】:

      不太清楚你在这里问什么,但我会试一试:

      class Program
      {
          class A
          {
              public static List<A> MyProperties = new List<A>();
              public int Id { get; set; }
              public string Value { get; set; }
          }
      
          static void Main(string[] args)
          {
              A a = new A() { Id = 1, Value = "Test" };
              A.MyProperties.Add(a);
              MyMethod(1);
          }
      
          static void MyMethod(int id)
          {
              var instance = A.MyProperties.First(link => link.Id == id);
              Console.WriteLine(instance.Value);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-17
        • 1970-01-01
        • 2010-11-21
        • 2018-12-08
        • 2022-01-23
        • 2020-07-24
        相关资源
        最近更新 更多