Avatar billede 123maka Nybegynder
31. januar 2009 - 17:57 Der er 5 kommentarer og
1 løsning

Dynamisk konfiguration og string matching af class

Hej,
Jeg vil gerne lave en konfigurations fil til mit program. Jeg er blevet glad for følgende syntax:
NAME
check:CLASS=args

Name er bare en ressource der skal matche noget internt i koden, checket er en boolsk værdi, klassen er et navn på en klasse og argumenterne er til klassens konstruktør.
For at komme med et reelt eksempel for en bil og dens strategier vil det se ud som følgende:

LightningMcQueen
engineStopped:engine="start"
carCrashed:mechanicalTeam="fix car"
default:Drive=

Min kode skal så scanne dem ind, se om klasserne eksisterer, og om de boolske værdier eksisterer, og hvis de gør skal de køres.
Kan man gøre dette i et kørende program dynamisk?

På forhånd tak
Avatar billede erikjacobsen Ekspert
31. januar 2009 - 20:34 #1
Avatar billede arne_v Ekspert
01. februar 2009 - 00:54 #2
Til inspiration:

using System;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;

namespace E
{
    public class Something
    {
        public bool engineStopped { get; set; }
        public bool carCrashed { get; set; }
        public bool @default { get; set; }
        private readonly Regex re = new Regex(@"(\w+):(\w+)=(""(.*)""|)");
        public void Process(string line)
        {
            Match m = re.Match(line);
            string check = m.Groups[1].Value;
            string clazz = m.Groups[2].Value;
            bool usearg = (m.Groups[3].Value == @"""" + m.Groups[4].Value + @"""");
            string arg = m.Groups[4].Value;
            if((bool)this.GetType().GetProperty(check).GetValue(this, null))
            {
                Type t = Assembly.GetExecutingAssembly().GetType("E." + clazz);
                if(usearg)
                {
                    ConstructorInfo ci = t.GetConstructor(new Type[] { typeof(string) } );
                    object o = ci.Invoke(BindingFlags.Default, null, new object[] { arg }, null);
                }
                else
                {
                    ConstructorInfo ci = t.GetConstructor(new Type[0]);
                    object o = ci.Invoke(BindingFlags.Default, null, new object[0], null);
                }
            }
           
        }
        public void Process(string fnm, string section)
        {
            using(StreamReader sr = new StreamReader(fnm))
            {
                bool active = false;
                string line;
                while((line = sr.ReadLine()) != null)
                {
                    if(active)
                    {
                        if(line.Contains(":") && line.Contains("="))
                        {
                            Process(line);
                        }
                        else
                        {
                            active = false;
                        }
                    }
                    else if(line == section)
                    {
                        active = true;
                    }
                }
            }
        }
        public static void Main(string[] args)
        {
            Something o = new Something();
            o.engineStopped = true;
            o.carCrashed = true;
            o.@default = true;
            o.Process(@"C:\cfg.txt", "LightningMcQueen");
            Console.ReadKey();
        }
    }
    public class engine
    {
        public engine(string s)
        {
            Console.WriteLine("engine " + s);
        }
    }
    public class mechanicalTeam
    {
        public mechanicalTeam(string s)
        {
            Console.WriteLine("mechanicalTeam " + s);
        }
    }
    public class Drive
    {
        public Drive()
        {
            Console.WriteLine("Drive");
        }
    }
}
Avatar billede 123maka Nybegynder
12. februar 2009 - 16:44 #3
Det har taget lidt tid at kigge igennem, og skære ud for at få forståelsen korrekt. Det ser ud til at virke med en del modifikationer. For at hjælpe andre med lignende problemer i fremtiden burde man kigge på følgende linjer:

Denne kigger efter om en variabel i koden er true eller false. Gætter på den siger false hvis den ikke findes i konteksten.
if((bool)this.GetType().GetProperty(check).GetValue(this, null))

Og så de følgende:
Type t = Assembly.GetExecutingAssembly().GetType("E." + clazz);
ConstructorInfo ci = t.GetConstructor(new Type[] { typeof(string) } );
object o = ci.Invoke(BindingFlags.Default, null, new object[] { arg }, null);

Opretter du svar arne?
Avatar billede arne_v Ekspert
12. februar 2009 - 17:05 #4
Den foerste tester om flaget er sat. Jeg tror at du faar en exception hvis den slet ikke eksisterer.

Den sidste instantierer et objekt via reflection med nogle argumenter til constructor.

Og svar.
Avatar billede arne_v Ekspert
12. februar 2009 - 17:06 #5
Og reflection kan nemt blive noget ulaeseligt. Og p.g.a. det og p.g.a. performance overhead er det noget som kun skal bruges hvis det er absolut noedvendigt.
Avatar billede kawsper Nybegynder
05. maj 2009 - 15:24 #6
Du kunne også kigge på en activator.

Vil du instantiere DitProjekt.DinKlasse af typen DinType kan du instantiere den således:
DinType plugin = (DinType)Activator.CreateInstance(Type.GetType("DitProjekt.DinKlasse"));
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester