C#:如何设置对象';通过向其传递变量名和值来初始化成员

C#:如何设置对象';通过向其传递变量名和值来初始化成员,c#,.net,reflection,C#,.net,Reflection,我有一个具有许多属性(所有字符串)的类。我动态地接收要设置的属性的名称(和值)。如果要设置正确的变量,则不希望执行100。我想称之为: Person.setVar(string propname, string propvalue) 我尝试了以下几点(基于我对这里的各种帖子的有限理解): 使用系统; 运用系统反思; 命名空间错误测试{ 公共阶层人士{ 公共字符串personName; 公众人物; public void SetVar(字符串propName、字符串propValue){ Pr

我有一个具有许多属性(所有字符串)的类。我动态地接收要设置的属性的名称(和值)。如果要设置正确的变量,则不希望执行100。我想称之为:

Person.setVar(string propname,  string propvalue)
我尝试了以下几点(基于我对这里的各种帖子的有限理解):

使用系统;
运用系统反思;
命名空间错误测试{
公共阶层人士{
公共字符串personName;
公众人物;
public void SetVar(字符串propName、字符串propValue){
PropertyInfo-propInfo=this.GetType().GetProperty(propName);

基于Sean Kelly的建议:类成员是字段(不是属性),因此我需要获取FieldInfo而不是GetProperties。因此,将代码更改为:

    public void SetVar(string propName, string propValue){
        FieldInfo fieldInfo = this.GetType().GetField(propName);
        fieldInfo.SetValue(this, propValue);
    }
它现在可以工作了!

编辑: 因此,在阅读了OP对我下面问题的回答后,这里有几个问题:

为什么代码失败?

代码失败的原因是
personName
personAge
是公共字段,而不是属性,因此您可能应该使用

字段和属性之间有什么区别?

字段是每个类实例(每个对象)都存在的变量。任何有权访问该字段的人都可以直接修改该字段(取决于受保护的
/
私有
关键字定义的可访问性)

C#中的可以被认为是一个“getter”(和“setter”(如果定义的话)函数。通常(但不总是)它们为某个私有字段(也称为“backing field”)提供一个抽象层,以防止任何人直接修改该字段。而不是使用
GetAge()
&
SetAge(int age)
方法,我们可以写:

private int _age
public int Age
{
    get
    {
        return _age;
    }
    set
    {
        _age = value;
    }
} 
我们可以简单地编写
public int Age{get;set;}
(也称为自动属性)。这允许我们编写
if(somePerson.Age==3)
而不是
if(somePerson.GetAge()==3)
,以及
somePerson.Age=4
而不是
somePerson.SetAge(4)
。这只是一条捷径

你可能会问,getter和setter的意义是什么,为什么不简单地拥有一个公共字段而忽略所有这些无意义的内容,答案是当你公开一个字段时,你对类的使用方式的控制就更少了我可以将
public int{get;set;}
更改为:

private int _age
public int Age
{
    get
    {
        return _age;
    }
    set
    {
        if(value == 13)
        {
            RaiseBarMitzvahEvent();
        }
        _age = value;
    }
} 
我不能对公共字段执行同样的操作(除非我将其更改为属性)

你真正应该做什么 我不知道你是否有时间或资源重构100个大字段的大型类,但为了将来编写C#代码,你应该:

  • 避免使用大型类。类不应该包含100个字段(私有的,绝对不是公共的)。您可能应该将其拆分为多个类,使用组合并遵循以下步骤
  • 当您想要动态设置多个数据点时,您可能希望使用字典之类的东西,而不是许多不同的字段。尤其是当您的所有属性都是字符串时,您可以简单地使用
    person.SomeDictionaryName[propName]=propValue
  • 避免使用公共字段。在几乎所有使用公共字段的情况下,您都可以使用自动属性(您也应该避免使用自动属性,但这更主观)
  • 当你发现自己在使用反射时,通常有更好的方法来处理你正在做的事情
起初的 为什么不简单地:

personInstance.personName = "Some Name";

当字段已经公开时,为什么需要所有额外的代码和反射无意义?当您已经可以通过简单地使用赋值运算符(
=
)设置“变量”(实际字段)时,为什么要使用
SetVar
函数?

是否在函数中设置断点,并确保
propInfo
不为null?如果未找到属性名称,则返回null。此外,
personName
personAge
是字段,而不是属性(no-get;set;)。你需要
FieldInfo
。试试这个想法。@Sean Skelly…你是对的。propInfo是空的。我不理解字段和属性之间的区别。我现在可以使用它,并将在我的原始帖子中向我的代码添加更新。非常感谢。你为什么要这样做?为什么不简单地
obj.property=something
?还要注意字段和属性之间的差异太好了!很高兴它起到了作用。您也可以将自己的答案标记为已接受,不过,您需要等待48小时,以防其他人出现并提供您更喜欢的答案。最后,根据我在您的问题评论中发布的链接,我建议您已接受您的代码同时处理字段和属性,因此您的
SetVar
方法在将来是灵活的。您或其他人可能会出现并向此类添加属性,而忘记
SetVar
仅处理字段。好的建议。可以。因为类中几乎有100个字段,并且要设置字段/值来自我无法控制的其他地方的es。想要避免类似:if(fieldname=“xyz”)person.xyz=fieldvalue…a 100次。好吧,我理解你的问题。听起来这只是一个糟糕的设计,你试图在C#这是一种静态语言中引入一些duck类型。我将编辑我的答案以更彻底地回答,因为这里有几个问题。我现在回答了你的问题,并解释了字段与属性还有一些额外的提示
private int _age
public int Age
{
    get
    {
        return _age;
    }
    set
    {
        if(value == 13)
        {
            RaiseBarMitzvahEvent();
        }
        _age = value;
    }
} 
personInstance.personName = "Some Name";