TOC

This article has been localized into Czech by the community.

Reflexe:

Třída pro nastavení založená na reflexi

Takže jsem si myslel, že bych tuto část tutoriálu o reflexi zakončil chladným a užitečným příkladem. Je trochu větší než obvyklé příklady zde na webu, ale doufám, že jej shledáte opravdu užitečným. Využívá spoustu věcí, na které jsme se během posledních několika kapitol dívali, takže doufám, že budete moci držet krok.

Běžný scénář při vytváření jakéhokoli typu aplikace je touha uložit nastavení uživatelů. Když máte několik nastavení, pravděpodobně vytvoříte třídu Settings, která bude zpracovávat načítání a ukládání požadovaných nastavení. Pokaždé, když potřebujete v třídě Settings nové nastavení, budete muset aktualizovat metody Load() a Save(), aby zahrnovaly toto nové nastavení. Ale proč nenechat třídu Settings objevit její vlastní vlastnosti a poté je automaticky načítat a ukládat? S reflexí je to docela snadné, a pokud jste četli ostatní kapitoly v sekci o reflexi tohoto tutoriálu, měli byste být schopni pochopit následující příklad.

Aby to lépe zapadlo do malého příkladu, ukládám informace o osobě namísto nastavení aplikace, ale doufám, že stejně dostanete obecnou představu. Mějte na paměti, že použití reflexe BUDE pomalejší než ruční čtení a zápis známých vlastností, takže byste měli zvážit, kdy ji použít a kdy zvolit rychlejší přístup! Také, v našem příkladu, používáme jednoduchý textový soubor pro ukládání ještě jednodušších hodnot, oddělených pouze znakem | (svislítko). Pokud toto používáte pro skutečné věci, pravděpodobně budete chtít pro vaše data lepší formát, možná XML. A samozřejmě, zde chybí zpracování chyb, takže byste pravděpodobně měli přidat i to.

Dobře, pojďme začít. Nejprve naše třída Person (Osoba), kterou můžete jednoduše přejmenovat na Settings (Nastaveni) nebo něco podobného, aby to bylo pro vás užitečnější:

public class Person
{
    private int age = -1;
    private string name = String.Empty;

    public void Load()
    {
        if(File.Exists("settings.dat"))
        {
            Type type = this.GetType();

            string propertyName, value;
            string[] temp;
            char[] splitChars = new char[] { '|' };
            PropertyInfo propertyInfo;

            string[] settings = File.ReadAllLines("settings.dat");
            foreach(string s in settings)
            {
                temp = s.Split(splitChars);
                if(temp.Length == 2)
                {
                    propertyName = temp[0];
                    value = temp[1];
                    propertyInfo = type.GetProperty(propertyName);
                    if(propertyInfo != null)
                        this.SetProperty(propertyInfo, value);
                }
            }
        }
    }

    public void Save()
    {
        Type type = this.GetType();
        PropertyInfo[] properties = type.GetProperties();
        TextWriter tw = new StreamWriter("settings.dat");
        foreach(PropertyInfo propertyInfo in properties)
        {
            tw.WriteLine(propertyInfo.Name + "|" + propertyInfo.GetValue(this, null));
        }
        tw.Close();
    }

    public void SetProperty(PropertyInfo propertyInfo, object value)
    {
        switch(propertyInfo.PropertyType.Name)
        {
            case "Int32":
                propertyInfo.SetValue(this, Convert.ToInt32(value), null);
                break;
            case "String":
                propertyInfo.SetValue(this, value.ToString(), null);
                break;
        }
    }

    public int Age
    {
        get { return age; }
        set { age = value; }
    }

    public string Name
    {
        get { return name; }
        set { name = value; }
    }
}

Ano, je toho hodně, vím. Ale pomohu vám s celou třídou. Především máme několik privátních polí pro uchování informací o naší osobě. Na konci třídy máme odpovídající veřejné vlastnosti, které samozřejmě využívají privátní pole.

Máme také metodu Load(). Hledá soubor settings.dat a pokud existuje, přečte celý soubor a umístí každou jeho řádku do pole řetězců. Nyní procházíme každou řádku nastavení a rozdělíme ji na dvě části: název vlastnosti a hodnotu. Pokud je obojí přítomno, jednoduše použijeme objekt Type k získání vlastnosti s názvem vlastnosti a poté nastavíme její hodnotu pomocí naší vlastní metody SetProperty.

Metoda SetProperty() se dívá na typ vlastnosti, která má být změněna, a poté odpovídajícím způsobem jedná. V současnosti podporuje pouze celá čísla a řetězce, ale jak si pravděpodobně uvědomujete, rozšíření této podpory by bylo poměrně snadné.

Metoda Save() získá pole instancí PropertyInfo, jednu pro každou definovanou vlastnost třídy Person, a poté použije TextWriter k zapsání každé vlastnosti a její hodnoty do datového souboru.

Nyní potřebujeme jen nějaký kód, který tuto třídu použije. Tato malá aplikace se pokusí načíst osobu ze souboru s nastaveními a pokud se to nepodaří, uživatel je vyzván k zadání informací:

class Program
{
    static void Main(string[] args)
    {
        Person person = new Person();
        person.Load();
        if((person.Age > 0) && (person.Name != String.Empty))
        {
            Console.WriteLine("Hi " + person.Name + " - you are " + person.Age + " years old!");
        }
        else
        {
            Console.WriteLine("I don't seem to know much about you. Please enter the following information:");
            Type type = typeof(Person);
            PropertyInfo[] properties = type.GetProperties();
            foreach(PropertyInfo propertyInfo in properties)
            {
                Console.WriteLine(propertyInfo.Name + ":");
                person.SetProperty(propertyInfo, Console.ReadLine());
            }
            person.Save();
            Console.WriteLine("Thank you! I have saved your information for next time.");
        }
        Console.ReadKey();
    }
}

Vše zde je poměrně triviální, až na část, kde požádáme uživatele o informace. Opět používáme reflexi, abychom získali všechny veřejné vlastnosti třídy Person, a poté se na každou z nich zeptáme.

Jako cvičení pro čtenáře navrhuji rozšířit třídu Osoba o další informace. Stačí přidat další vlastnosti a uvidíte, že se tyto informace také uloží a načtou.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!