我想知道c#中是否有能够将类的成员传递给另一个将使用此成员获取值的函数。因此,获取在运行时仅确定哪一个字段的值。像其他语言(至少我认为PHP)你可以做的事情
a.b = "something"
但也
a["b"] = "something";
编辑:由于使用了字符串,实际上不是很好的例子,抱歉
为清楚起见,我希望能够做到的一个例子:
class A
{
int x;
int y;
}
void somethingsomething<T>(T class, SomeMagicFieldClass f)
{
dosomethingwith(somemethodthatgivesmethevalueoffield(class, f));
}
然后我可以这样调用这个方法:
A a = new A();
somethingsomething(a, A.x); //hypothetical notation
somethingsomething(a, A.y);
我现在有类似的地方:
somethingsomething(a, "x");
somethingsomething(a, "y");
然后我使用内省API(也尝试GetProperty)找到该字段
MemberInfo memberInfo = item.GetType().GetField(fieldName);
这样可行,但缺点是在视觉工作室中“重构”字段名时,作为字符串传递的字段不会更新,所以我想也许在c#中存在这样的东西会在更改字段时自动重构名字?
非常感谢您阅读这个无聊的问题
答案 0 :(得分:4)
您的示例看起来很像LINQ键选择器,在该表单中看起来像:
A a = new A();
somethingsomething(a, p => p.x);
答案 1 :(得分:1)
你可以使用LINQ Expressions做一些很好的重构友好的东西。这是我用于此类场合的实用代码片段。它允许您获取属性的名称,类型和值(它不适用于没有修改的字段)。还有一个价值的设定者。
public static void Main(string[] args) {
var test = new { Test1 = 42, Test2 = "123", Test3 = 3.14195 };
somethingSomething(test, t => t.Test1);
somethingSomething(test, t => t.Test2);
somethingSomething(test, t => t.Test3);
}
static void somethingSomething<TObj,TProperty>(TObj obj, Expression<Func<TObj,TProperty>> expr) {
var accessor = GetMemberAccessor(expr, obj);
String name = accessor.Name;
TProperty value = accessor.Value;
String typeName = accessor.Type.Name;
Console.WriteLine("{0} = {1} ({2})", name, value, typeName);
}
输出结果为:
Test1 = 42 (Int32)
Test2 = 123 (String)
Test3 = 3.14195 (Double)
为了使这项工作,我使用了以下辅助函数和类:
public static MemberAccessor<TReturn> GetMemberAccessor<TObj,TReturn>(Expression<Func<TObj, TReturn>> expr, TObj tar) {
var body = expr.Body;
MemberExpression memberExpression = null;
if (body is UnaryExpression) {
var ue = (UnaryExpression)body;
memberExpression = (MemberExpression)ue.Operand;
} else if (body is MemberExpression)
memberExpression = (MemberExpression)body;
else
throw new NotImplementedException("can't get MemberExpression");
String name = memberExpression.Member.Name;
return new MemberAccessor<TReturn>(tar, name);
}
public class MemberAccessor<T> {
private readonly PropertyDescriptor propertyDesc;
private readonly Object target;
public MemberAccessor(Object target, String propertyName) {
this.target = target;
this.propertyDesc = TypeDescriptor.GetProperties(target)[propertyName];
}
public String Name {
get { return propertyDesc.Name; }
}
public Type Type {
get { return propertyDesc.PropertyType; }
}
public T Value {
get { return (T)Convert.ChangeType(propertyDesc.GetValue(target), typeof(T)); }
set { propertyDesc.SetValue(target, value); }
}
}
答案 2 :(得分:0)
听起来像dynamic type可能会起作用。
答案 3 :(得分:0)
先生。 Plunkett是正确的;动态类型将完成这项工作。幸运的是,.NET 4团队包含了一个名为ExpandoObject的便捷对象,可以为您解决这个问题。
答案 4 :(得分:0)
你问过如何
将类的成员传递给另一个 将使用此成员的函数 得到一个值
您可以将delegates
用于此
class A
{
public string aField;
public string aProperty{get{return "someval";}}
public string aMemberFunction(){return "someval";}
}
void get_a_value(Func<string> func)
{
string theValue = func();
}
// use it:
A a = new A();
get_a_value( () => a.aField);
get_a_value( () => a.aProperty);
get_a_value( () => a.aMemberFunction());
当然,你不会这样做的是成员函数和你传递的对象的参数分离。