问题
How do I keep some sort of link to a class' property and then use that to access an instance's property? Thing is there are no class instances where the link is created. The idea is to remember the property before any instances can be accessed.
Here's an example:
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
}
Is there a way to do something like this in C#?
回答1:
It looks like you're looking for Reflection
Example:
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);
You still need a reference to set/get
values, but this seems about what you're wanting.
回答2:
If a property is a reference type - all you need is to keep a reference to the instance. Then you can change/modify public properties/fields (or call methods) of that instance.
If a property is a value type or if you need to change the reference itself (make it point to a new instance) - the only thing that is remotely close to what you are describing involves
PropertyInfo property = obj.GetType().GetProperty(<property name>);
and
object value = property.GetValue(obj, null);
property.SetValue(obj, newValue, null);
where you still need the reference to the instance whose property you want to get/set.
回答3:
You can write a property wrapper class that uses Reflection like so:
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);
}
}
}
And then you can use it like this:
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();
}
}
[Edit] I was compelled to return to this to post a way of doing it without reflection:
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();
}
}
回答4:
Not quite sure what you are asking here, but I'll give it a shot:
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);
}
}
来源:https://stackoverflow.com/questions/17045635/how-to-store-reference-to-class-property-and-access-an-instances-property-by-t