C# 以字符串形式访问对象属性并设置其值
我有一个C# 以字符串形式访问对象属性并设置其值,c#,string,eval,accessor,databinder,C#,String,Eval,Accessor,Databinder,我有一个帐户类的实例。每个帐户对象都有一个所有者、引用等 我可以访问帐户属性的一种方法是通过访问器,如 account.Reference; 但我希望能够使用动态字符串选择器访问它,如: account["PropertyName"]; 就像在JavaScript中一样。因此,我将拥有帐户[“Reference”],该帐户将返回值,但我也希望能够在此之后分配一个新值,如: account["Reference"] = "124ds4EE2s"; 我注意到我可以使用 DataBinder.E
帐户
类的实例。每个帐户对象都有一个所有者、引用等
我可以访问帐户属性的一种方法是通过访问器,如
account.Reference;
但我希望能够使用动态字符串选择器访问它,如:
account["PropertyName"];
就像在JavaScript中一样。因此,我将拥有帐户[“Reference”]
,该帐户将返回值,但我也希望能够在此之后分配一个新值,如:
account["Reference"] = "124ds4EE2s";
我注意到我可以使用
DataBinder.Eval(account,"Reference")
获取基于字符串的属性,但使用该属性我无法为该属性赋值
你知道我该怎么做吗?首先,你应该避免使用这个;C#是一种强类型语言,因此要充分利用与此相关的类型安全和性能优势 如果您有合理的理由动态获取和设置属性的值(换句话说,当代码中无法定义类型和/或属性名称时),那么您必须使用反射 最内联的方式是:
object value = typeof(YourType).GetProperty("PropertyName").GetValue(yourInstance);
...
typeof(YourType).GetProperty("PropertyName").SetValue(yourInstance, "value");
但是,您可以缓存PropertyInfo
对象以使其更具可读性:
System.Reflection.PropertyInfo prop = typeof(YourType).GetProperty("PropertyName");
object value = prop.GetValue(yourInstance);
...
prop.SetValue(yourInstance, "value");
您需要使用反射:
PropertyInfo property = typeof(Account).GetProperty("Reference");
property.SetValue(myAccount, "...", null);
请注意,这将非常缓慢。如果它们是您自己的对象,您可以提供一个索引器来访问这些字段。我真的不推荐这个,但它会让你想要什么
public object this[string propertyName]
{
get
{
if(propertyName == "Reference")
return this.Reference;
else
return null;
}
set
{
if(propertyName == "Reference")
this.Reference = value;
else
// do error case here
}
}
请注意,执行此操作时会失去类型安全性 我同意之前的海报,您可能确实需要使用这些属性。与直接属性访问相比,反射速度非常慢 另一方面,如果需要维护用户定义属性的列表,则不能使用C#属性。您需要假装自己是一个
字典
,或者需要公开一个行为类似于字典
的属性。下面是如何使Account类支持用户定义属性的示例:
public class Account
{
Dictionary<string, object> properties;
public object this[string propertyName]
{
get
{
if (properties.ContainsKey[propertyName])
return properties[propertyName];
else
return null;
}
set
{
properties[propertyName] = value;
}
}
}
公共类帐户
{
字典属性;
公共对象此[string propertyName]
{
得到
{
if(properties.ContainsKey[propertyName])
返回属性[propertyName];
其他的
返回null;
}
设置
{
属性[propertyName]=值;
}
}
}
您可以尝试将索引器与反射相结合
public object this[string propertyName]
{
get
{
PropertyInfo property = GetType().GetProperty(propertyName);
return property.GetValue(this, null);
}
set
{
PropertyInfo property = GetType().GetProperty(propertyName);
property.SetValue(this,value, null);
}
}
我个人更喜欢使用扩展方法,因此下面是我的代码:
public static class ReflectionExtensions
{
public static void SetPropertyValue(this object Target,
string PropertyName,
object NewValue)
{
if (Target == null) return; //or throw exception
System.Reflection.PropertyInfo prop = Target.GetType().GetProperty(PropertyName);
if (prop == null) return; //or throw exception
object value = prop.GetValue(Target, null);
prop.SetValue(Target, NewValue, null);
}
}
如果您使用的是.NET4,那么现在就可以使用dynamic关键字
dynamic foo = account;
foo.Reference = "124ds4EE2s";
我使用了Richard提供的反射方法,但详细阐述了set方法来处理其他类型,如字符串和空值
public object this[string propertyName]
{
get
{
PropertyInfo property = GetType().GetProperty(propertyName);
return property.GetValue(this, null);
}
set
{
PropertyInfo property = GetType().GetProperty(propertyName);
Type propType = property.PropertyType;
if (value == null)
{
if (propType.IsValueType && Nullable.GetUnderlyingType(propType) == null)
{
throw new InvalidCastException();
}
else
{
property.SetValue(this, null, null);
}
}
else if (value.GetType() == propType)
{
property.SetValue(this, value, null);
}
else
{
TypeConverter typeConverter = TypeDescriptor.GetConverter(propType);
object propValue = typeConverter.ConvertFromString(value.ToString());
property.SetValue(this, propValue, null);
}
}
}
如果转换不起作用,SetValue()函数将抛出错误。使用反射体和表达式体
public动态此[string memberName]
{
get=>GetType().GetProperty(memberName).GetValue(this,null);
set=>GetType().GetProperty(memberName).SetValue(this,value,null);
}
这里有一个简单的例子,希望对您有所帮助
static void Main(string[] args)
{
Operators op = new Operators()
{
ID = 1,
Name = "Edward",
email = "e.lorenz@mail.com",
Pass = "123456",
Auth1 = "EDF3242523@FFSDGDF"
};
var typei = op.GetType();
var ss = typei.GetProperties().Where(m => m.GetCustomAttributes<Password>().Count() > 0);
foreach (var item in ss)
{
var text = typei.GetProperty(item.Name).GetValue(op).ToString();
typei.GetProperty(item.Name).SetValue(op, Encrypt(text));
}
Console.WriteLine(op.Pass);
Console.WriteLine(op.Auth1);
Console.ReadKey();
}
static void Main(字符串[]args)
{
运算符op=新运算符()
{
ID=1,
Name=“爱德华”,
email=“e。lorenz@mail.com",
Pass=“123456”,
Auth1=”EDF3242523@FFSDGDF"
};
var typei=op.GetType();
var ss=typei.GetProperties(),其中(m=>m.GetCustomAttributes().Count()>0);
foreach(ss中的var项目)
{
var text=typei.GetProperty(item.Name).GetValue(op.ToString();
typei.GetProperty(item.Name).SetValue(op,Encrypt(text));
}
控制台写入线(op.Pass);
控制台写入线(op.Auth1);
Console.ReadKey();
}
你的意思是“C#”,不是吗,不是“csharp”?C#不是一种脚本语言;通常在学习一门新语言时;你需要学习与之配套的新习惯用法和惯例。+1对我也适用。请注意,您需要处理可能为null的属性。有人告诉我C#的类型太强。经过一番思考后,我认为它并没有那么糟糕。使用它来实现持久性,可以节省大量代码(更少的代码=更少的bug)。像ruby一样使用它,使您的db表与您的属性相匹配,并专注于算法,而不是没完没了的键入(包括强输入和键盘输入)