C# Reflection

やれると便利なリフレクション。
csvから適当にデータ作ったり、データを見たり
後はDTOのフィールド数が多いときとかに便利。

###Type取得

```cs:Program.cs
using System;

namespace ConsoleApp9
{
    class Program
    {
        static void Main(string[] args)
        {
            var fruit = new Fruit();
            Console.WriteLine(fruit.GetType());
        }
    }

    public class Fruit
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Price { get; set; }

        public int Number { private get; set; }
    }
}
```

実行結果

```
ConsoleApp9.Fruit
```

###フィールド名取得

```cs:Program.cs
using System;

namespace ConsoleApp9
{
    class Program
    {
        static void Main(string[] args)
        {
            var fruit = new Fruit();
            foreach(var prop in fruit.GetType().GetProperties())
            {
                Console.WriteLine(prop.Name);
            }
        }
    }

    public class Fruit
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Price { get; set; }

        public int Number { private get; set; }
    }
}
```

実行結果

```
Id
Name
Price
Number
```

###get,setの存在
setter,getterがあるかは、CanWrite,CanReadのフィールドで見ることができる。

```cs:Program.cs
using System;

namespace ConsoleApp9
{
    class Program
    {
        static void Main(string[] args)
        {
            var fruit = new Fruit();
            foreach(var prop in fruit.GetType().GetProperties())
            {
                Console.WriteLine("propName = {0}, Write = {1}", prop.Name, prop.CanWrite);
            }
        }
    }

    public class Fruit
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Price { get; set; }

        public int Number { get; } = 1;
    }
}
```

実行結果

```
propName = Id, Write = True
propName = Name, Write = True
propName = Price, Write = True
propName = Number, Write = False
```

###アクセッサーについて。

アクセッサーの取得。

```cs:Program.cs
using System;

namespace ConsoleApp9
{
    class Program
    {
        static void Main(string[] args)
        {
            var fruit = new Fruit();
            foreach(var prop in fruit.GetType().GetProperties())
            {
                Console.WriteLine("propName = {0}, Write = {1}", prop.Name, prop.GetAccessors()[0].Name);
            }
        }
    }

    public class Fruit
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Price { get; set; }

        public int Number { get; set; } = 1;
    }
}

```

実行結果

```
propName = Id, Write = get_Id
propName = Name, Write = get_Name
propName = Price, Write = get_Price
propName = Number, Write = get_Number
```

Numberのgetterをprivateにすると...?

```cs:Program.cs
using System;

namespace ConsoleApp9
{
    class Program
    {
        static void Main(string[] args)
        {
            var fruit = new Fruit();
            foreach(var prop in fruit.GetType().GetProperties())
            {
                Console.WriteLine("propName = {0}, Write = {1}", prop.Name, prop.GetAccessors()[0].Name);
            }
        }
    }

    public class Fruit
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Price { get; set; }

        public int Number { private get; set; } = 1;
    }
}
```

実行結果

```
propName = Id, Write = get_Id
propName = Name, Write = get_Name
propName = Price, Write = get_Price
propName = Number, Write = set_Number
```

ここだけset_Numberとなっている。

###Refrection 値取得

Fr.GetType().GetProperties()を実行した瞬間Fruitのフィールドの情報となっている。
prop.GetValueメソッドによって間接的に値を取得している。

```cs:Program.cs
using System;
using System.Collections.Generic;

namespace ConsoleApp9
{
    class Program
    {
        static void Main(string[] args)
        {
            var Fruit1 = new Fruit(1, "apple", 180, 5);
            var Fruit2 = new Fruit(2, "banana", 220, 7);
            var Fruit3 = new Fruit(3, "cherry", 210, 6);

            var Fruits = new List<Fruit>() { Fruit1, Fruit2, Fruit3 };
            foreach(var Fr in Fruits)
            {
                var props = Fr.GetType().GetProperties();
                foreach(var prop in props)
                {
                    Console.WriteLine("PropName = {0}, PropValue = {1}", prop.Name, prop.GetValue(Fr));
                }
                Console.WriteLine("**********************");
            }
        }
    }

    public class Fruit
    {
        public Fruit(int Id, string Name, int Price, int Number)
        {
            this.Id = Id;
            this.Name = Name;
            this.Price = Price;
            this.Number = Number;
        }

        public int Id { get; set; }
        public string Name { get; set; }
        public int Price { get; set; }
        public int Number { get; set; } = 1;
    }
}
```

実行結果

```
PropName = Id, PropValue = 1
PropName = Name, PropValue = apple
PropName = Price, PropValue = 180
PropName = Number, PropValue = 5
**********************
PropName = Id, PropValue = 2
PropName = Name, PropValue = banana
PropName = Price, PropValue = 220
PropName = Number, PropValue = 7
**********************
PropName = Id, PropValue = 3
PropName = Name, PropValue = cherry
PropName = Price, PropValue = 210
PropName = Number, PropValue = 6
**********************
```

###Refrection 値セット

prop.SetValue(a, b)によってaのprop.Name(フィールド名)をbに変更する。
下の場合だとFrオブジェクトのNameフィールドを"test"に変更する。
上の実行結果と見比べてみるときちんと値がセットされていることが分かる。

```cs:Program.cs
using System;
using System.Collections.Generic;

namespace ConsoleApp9
{
    class Program
    {
        static void Main(string[] args)
        {
            var Fruit1 = new Fruit(1, "apple", 180, 5);
            var Fruit2 = new Fruit(2, "banana", 220, 7);
            var Fruit3 = new Fruit(3, "cherry", 210, 6);

            var Fruits = new List<Fruit>() { Fruit1, Fruit2, Fruit3 };


            foreach(var Fr in Fruits)
            {
                var props = Fr.GetType().GetProperties();
                foreach (var prop in props)
                {
                    if (prop.Name == nameof(Fr.Name)) prop.SetValue(Fr, "test");
                }
            }

            foreach(var Fr in Fruits)
            {
                var props = Fr.GetType().GetProperties();
                foreach(var prop in props)
                {
                    Console.WriteLine("PropName = {0}, PropValue = {1}", prop.Name, prop.GetValue(Fr));
                }
                Console.WriteLine("**********************");
            }
        }
    }

    public class Fruit
    {
        public Fruit(int Id, string Name, int Price, int Number)
        {
            this.Id = Id;
            this.Name = Name;
            this.Price = Price;
            this.Number = Number;
        }

        public int Id { get; set; }
        public string Name { get; set; }
        public int Price { get; set; }
        public int Number { get; set; } = 1;
    }
}
```

実行結果

```
PropName = Id, PropValue = 1
PropName = Name, PropValue = test
PropName = Price, PropValue = 180
PropName = Number, PropValue = 5
**********************
PropName = Id, PropValue = 2
PropName = Name, PropValue = test
PropName = Price, PropValue = 220
PropName = Number, PropValue = 7
**********************
PropName = Id, PropValue = 3
PropName = Name, PropValue = test
PropName = Price, PropValue = 210
PropName = Number, PropValue = 6
**********************
```