C# calling all properties, for each loop

廉价感情. 提交于 2020-01-06 15:01:31

问题


I have a foreach loop and I would like to call all properties of a certain class in the foreach loops so I don't have to write it all out.

The class I have created

public Person()
    {
        firstname = "";
        surname = "";
        haircolor = "";
        eyecolor = "";
        weight = 0;
        height = 0;
        age = 0;
    }

This is the code I am trying to compact

  Console.WriteLine("Please enter the next persons firstname");//new person user input (firstname)
  addperson.firstname = Console.ReadLine();

  Console.WriteLine("Enter the persons surname");//surname
  addperson.surname = Console.ReadLine();

  Console.WriteLine("Enter " + addperson.name + "'s hair color");//hair color
  addperson.haircolor = Console.ReadLine();

  Console.WriteLine("Enter the age of " + addperson.firstname);//age
  addperson.age = Convert.ToInt32(Console.ReadLine());

  Console.WriteLine("Enter the weight of " + addperson.firstname);//weight
  addperson.weight = Convert.ToDouble(Console.ReadLine());

  Console.WriteLine("Enter the height of " + addperson.firstname);//height
  addperson.height = Convert.ToDouble(Console.ReadLine());

I have started on the foreach loop, I would like a way to compact all of that code to a loop

  foreach (Person.)
            {
                Console.WriteLine("Please enter " +addperson.ToString);
                  Person.addperson = Console.ReadLine();
            }

Any help would be much appreciated


回答1:


you need to use reflection to be able to loop over each property dynamically, personally i wont change it to use reflection since reflection has performance penalties, but here is the code for your reference:

Change Class fields to properties:

    public class Person
    {
      public string firstname {get;set;}
      public string surname {get;set;}
      public string haircolor {get;set;}
      public string eyecolor {get;set;}
      public string weight {get;set;}
      public string height {get;set;}
      public string age {get;set;}
     }

Write this code in your main method:

       Person addperson = new Person();
       PropertyInfo[] props = addperson.GetType().GetProperties();

        foreach(PropertyInfo prop in props)
        {
              Console.WriteLine("Please enter " + prop.Name.ToString());
              string input = Console.ReadLine();
              prop.SetValue(addperson, input, null);
        }

EDIT:

This line of code:

 PropertyInfo[] props = addperson.GetType().GetProperties();

Returns all the public properties of the Person type (class), then each PropertyInfo object discovers the attributes of the property and provides access to its metadata.




回答2:


I'd do it like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace YourNameSpace
{
    class Program
    {
        static void Main(string[] args)
        {
            Person p = GetPersonFromUserInput();
        }

        private static Person GetPersonFromUserInput()
        {
            Person p = new Person();
            Type t = typeof(Person);
            foreach (PropertyInfo pi in t.GetProperties().Where(pi => pi.GetCustomAttribute<PromptAttribute>() != null))
            {
                PromptAttribute attribute = pi.GetCustomAttribute<PromptAttribute>();

                Console.Write("{0}: ", pi.GetCustomAttribute<PromptAttribute>().Prompt);

                if (pi.PropertyType == typeof(int))
                {
                    PromptInteger(p, pi);
                }
                else if (pi.PropertyType == typeof(string))
                {
                    PromptString(p, pi);

                } //add more types in this manner                           
            }

            return p;
        }

        private static void PromptString(Person p, PropertyInfo pi)
        {
            string userInput = Console.ReadLine();
            pi.SetMethod.Invoke(p, new object[] { userInput });
        }

        private static void PromptInteger(Person p, PropertyInfo pi)
        {
            int userInput;
            while (!int.TryParse(Console.ReadLine(), out userInput))
            {
                Console.Write("You have to enter an integer: ");
            }

            pi.SetMethod.Invoke(p, new object[] { userInput });
        }


    }

    public class Person
    {
        [Prompt("Please enter the persons firstname")]
        public string FirstName { get; set; }

        [Prompt("Please enter the persons surname")]
        public string SurName { get; set; }

        [Prompt("Please enter the persons haircolor")]
        public string HairColor { get; set; }

        [Prompt("Please enter the persons eyecolor")]
        public string EyeColor { get; set; }

        [Prompt("Please enter the persons weight")]
        public int Weight { get; set; }

        [Prompt("Please enter the persons height")]
        public int Height { get; set; }

        [Prompt("Please enter the persons age")]
        public int Age { get; set; }
    }

    public class PromptAttribute : Attribute
    {
        public string Prompt { get; private set; }

        public PromptAttribute(string prompt)
        {
            Prompt = prompt;
        }
    }
}

Using the custom - attribute you could define the prompt. if you have more types just add more else ifs in the loop.




回答3:


A simple console app, using reflection, linq and a dictionary:

using statements:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

Your Class:

public class Person
{
  public string  firstname {get; set;}
  public string surname { get; set; }
  public string haircolor { get; set; }
  public string eyecolor { get; set; }
  public string weight { get; set; }
  public string height { get; set; }
  public string age { get; set; }
}

Console Application:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            var per = new Person();
            var perDict = new Dictionary<string, string>();


            foreach (
                var c in 
                    per.GetType()
                        .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                            .ToDictionary(prop => prop.Name, prop => prop.GetValue(per,null))
                        )
            {

            Console.Write("Greetings, Please Enter Your Value for: " + c.Key + " ");
            var answer = Console.ReadLine();
            perDict.Add(c.Key, answer);
            per.GetType().GetProperty(c.Key).SetValue(per,answer, null);
            }
        }
    }

}


来源:https://stackoverflow.com/questions/29514987/c-sharp-calling-all-properties-for-each-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!