Avatar billede gargazol Nybegynder
19. marts 2011 - 15:49 Der er 18 kommentarer og
1 løsning

XElement.Element bryder ud af min lykke/metode

Hej

Jeg har en metode til at hente settings ind i mit program fra en XML fil.

Dertil bruger jeg XDocument og XElement

public void LoadSettings()
        {
            if (File.Exists(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\OnOff\\Client\\Settings.xml"))
            {
                XDocument xDoc = XDocument.Load(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\OnOff\\Client\\Settings.xml");
                XElement settings = xDoc.Element("Settings");
                XElement servers = settings.Element("Servers");

                lbServers.BeginUpdate();
                foreach (XElement server in servers.Elements())
            {
                          string ip = server.Element("IP").Value;

            }
                MessageBox.Show("did complete the code");
                lbServers.EndUpdate();
            }
        }


XML dokumentet

<?xml version="1.0" encoding="utf-8"?>
<Settings>
<Servers>
  <Server0 ID="Media-Server" MAC="00-1D-60-56-3D-E4" IP="10.0.0.99" Port="6767" />
  <Server1 ID="Media-Server2" MAC="00-1D-60-56-3D-E3" IP="10.0.0.98" Port="6766" />
</Servers>
</Settings>


Mit problem er nu at jeg har ændret struktur i min XML dokument så det ikke længere ser sådan ud men min load funktion skal så lave en exeption fordi den ikke kan finde et Element ved navn IP.

Det der istedet sker at at når den når til linien hvor den skal sætte IP ind, så hopper den direkte ud af foreach lykken OG metoden uden at kaste en exeption eller køre resten af koden.
dvs. at jeg aldrig får en messagebox op men mit program går videre.
Denne metode bliver kørt i OnLoad

Hvad sker der?

Jeg har aldrig haft kode der opfører sig på den måde før
Avatar billede arne_v Ekspert
19. marts 2011 - 16:20 #1
servers.Elements() returnerer vel nul elementer, så løkken aldrig bliver kørt!?
Avatar billede gargazol Nybegynder
19. marts 2011 - 16:32 #2
servers.Elements() returnerer 2 elements

<Server0 ID="Media-Server" MAC="00-1D-60-56-3D-E4" IP="10.0.0.99" Port="6767" />
  <Server1 ID="Media-Server2" MAC="00-1D-60-56-3D-E3" IP="10.0.0.98" Port="6766" />

Men da server.Element("IP").Value; forsøger at hente et element, og "Ip" er en attribute, så den burde ikke kunne finde noget.

Det er string ip = server.Element("IP").Value; der laver baladen og bryder lykken/metoden
Avatar billede Red0z Nybegynder
19. marts 2011 - 16:41 #3
Hvor skal den gemme ip'en? Lige nu laver den en streng i Løkken og når løkken slutter forsvinder strengen vel?
Avatar billede Red0z Nybegynder
19. marts 2011 - 16:45 #4
Jeg går ud fra ipen skal opdateres.

Så i dit foreach, skal der så ikke stå lbServers.Update(server.Element("IP").Value) eller lign?
Avatar billede gargazol Nybegynder
19. marts 2011 - 16:47 #5
Alt den interne kode for brug af ip strengen fjernede jeg for ikke at gøre inlæget for langt.

Pointen er at string ip = server.Element("IP").Value; bryder det hele
Avatar billede Red0z Nybegynder
19. marts 2011 - 16:50 #6
Har du prøvet .ToString() ?
Avatar billede arne_v Ekspert
19. marts 2011 - 16:52 #7
Jeg tror at den kaster en exception men at du fanger den et forkert sted.

Jeg har lige testet:

using System;
using System.Linq;
using System.Xml.Linq;

namespace E
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string s = @"<?xml version='1.0' encoding='utf-8'?>
<Settings>
<Servers>
  <Server0 ID='Media-Server' MAC='00-1D-60-56-3D-E4' IP='10.0.0.99' Port='6767' />
  <Server1 ID='Media-Server2' MAC='00-1D-60-56-3D-E3' IP='10.0.0.98' Port='6766' />
</Servers>
</Settings>";
            XDocument xDoc = XDocument.Parse(s);
            XElement settings = xDoc.Element("Settings");
            XElement servers = settings.Element("Servers");
            foreach (XElement server in servers.Elements())
            {
                string ip = server.Element("IP").Value;
                Console.WriteLine(ip);
            }
            Console.ReadKey();
        }
    }
}

og det giver en fin exception.
Avatar billede gargazol Nybegynder
19. marts 2011 - 17:01 #8
ToString() gør det samme.



arne_v: Jeg prøvede lige at køre filen uden om VS 2010 og der giver den en exeption. Den giver intet når jeg kører den i vs 2010

Har jeg fået trykket på noget i VS 2010?
Avatar billede Red0z Nybegynder
19. marts 2011 - 17:03 #9
Hvilken exception kaster den? Har ikke et test miljø liggende
Avatar billede gargazol Nybegynder
19. marts 2011 - 17:05 #10
Object reference not set to an instance of an object.

Det er jo også helt rigtigt da den prøver at lave null om til string.

Det mærkelige er nu at den kommer hvis jeg kører mit program uden om vs 2010 eller med ctrl+F5 (uden debugging)
Avatar billede Red0z Nybegynder
19. marts 2011 - 17:09 #11
                XDocument xDoc = XDocument.Load(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\OnOff\\Client\\Settings.xml");

Hvad hvis den hed

                XDocument xDoc = new XDocument.Load(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\OnOff\\Client\\Settings.xml");
?
Avatar billede gargazol Nybegynder
19. marts 2011 - 17:13 #12
Red0z: Det ser ikke ud til der er noget galt med koden, men med VS2010 (SP1) eller en settings jeg har ramt, der gør at den kører videre istedet for at give mig den exeption.

Den giver exeption uden om VS2010 eller uden debugg Ctrl+F5

Men hvad jeg har ramt eller om det er en fejl har jeg ingen ide om
Avatar billede Red0z Nybegynder
19. marts 2011 - 17:19 #13
The item may not be in the menu, which you can fix by customising the menu and adding the item to the debug menu.

You should also be able to get to the exceptions menu using CTRL + ALT + E

You need to tick the box in the "Thrown" column for Common Language Runtime exceptions (CLR)

Fandt dette på StackOverfloe, prøv evt. Det
Avatar billede gargazol Nybegynder
19. marts 2011 - 17:25 #14
Det løste det hele Red0z!

Det må være ændret da jeg installerede SP1 til VS2010

Når jeg trykker "reset to default", så fjerner den selv "Thrown" fra alt. Yderst mærkeligt

Smid et svar så skal du få dine points :)
Avatar billede Red0z Nybegynder
19. marts 2011 - 17:27 #15
Det var så lidt :)
God fornøjelse!
Avatar billede janus_007 Nybegynder
19. marts 2011 - 20:19 #16
Nu er spørgsmålet afsluttet og fair nok.. men det er altså totalt overgjort imho.

Hvorfor ikke bare bruge settings file?

anyway... hvis du stadig vil bruge din egen xml, så lad være med at tjekke for om file exists, du skal håndtere dine exceptions istedet.

Når du så skal ha dine ip'er ud så...

var ips = xDoc.Root.Element("Servers").Elements().Attributes("IP");

så får du en fin liste af XAttributes ud, hvis du vil have de konkrete Ip'er.

var ips = xDoc.Root.Element("Servers").Elements().Attributes("IP").Select(x => x.Value);

så får du en enumerable string af ip's.

Dvs. du går fra 10-14 linjer til en linje, som tilmed er nem at forstå :)

Et andet lille tip er at du bryder single responsibility, du har hæftet en label ind i din kode, det skal du klare med events :)
Avatar billede gargazol Nybegynder
19. marts 2011 - 22:39 #17
janus_007:

Nu er programmering bare en hobby, så du må lige udybe lidt :)

Er det ikke bedre/hurtigere at sørge for man ikke for exeptions istedet for at basere sin kode på at få dem?

Som skrevet tidligere, så ser min XML fil ikke sådan ud mere, men istedet for attributes, så er info'en som elements.

Og det sidste med label kan jeg slet ikke forstå noget af.
Hvis det er lbServers du mener så er det en ListBox

MessageBox.Show er der på grund af den fejl jeg havde med visual studio, så jeg viste når jeg havde fundet fejlen. Den er slettet igen.


Min nye XML fil ser sådan ud:
<?xml version="1.0" encoding="utf-8"?>
<Settings>
<Servers>
<Server>
<ID>Media-Server</ID>
<MAC>00-1D-60-56-3D-E4</MAC>
<IP>10.0.0.99</IP>
<Port>6767</Port>
</Server>
</Servers>
</Settings>

Jeg bruger XML fordi jeg syntes det er nemmere at håntere. Har brugt settings før men der havde jeg problemer med tab a settings hvis program filen blev flyttet osv.


Inde i lykken af servers har jeg denne. Omen det nok ikke er optimalt at have mine data i en listbox, så syntes jeg det var nemmest.

lbServers.Items.Add(new Server(server.Element("IP").Value, int.Parse(server.Element("Port").Value), server.Element("MAC").Value, server.Element("ID").Value));
Avatar billede gargazol Nybegynder
19. marts 2011 - 22:42 #18
Og der kommer selvfølgelig exeption handling uden om, men jeg har til vane lige at få koden til at virke inden jeg sørger for at tage hensyn til fejl/exeptions som måske kan ske.

Koden er planlagt ind i en try/catch når jeg når dertil
Avatar billede janus_007 Nybegynder
20. marts 2011 - 12:13 #19
Hej gargazol

Nu så jeg at du gerne vil gøre tingene rigtigt, det er derfor jeg nævner det :)

Ja, om man bruger settings eller xml er nu også en smagssag, jeg kan komme i tanke om gode og dårlige ting ved begge.

Mht. exceptions, så er det korrekt at der ofres noget performance på at kaste dem, men sålænge vi ikke snakker om et loop med tusindvis af throws betyder det intet bare at benytte sig af frameworkets exceptions. Lad os sige du skulle ind i tusindvis af filepaths, så vil jeg anbefale at tjekke først :)

Hvis du vil logge den særlige exception, så catch den først


catch(System.IO.FileNotFoundException e)
{... i dit tilfælde... skriv til UI'en eller hvordan du lige tænker brugeren skal have besked ...}

catch(Exception e)
{...}


Nu når har flyttet data ud fra attribut til element, så gør du bare sådan her:

var ips = xDoc.Root.Element("Servers").Elements("Server").Elements("IP").Select(x => x.Value);

tip:
.Elements("Server") kan også skrives som Elements() som tidligere, det kan du benytte dig af hvis du navngiver elementerne Server1, Server2 osv. som tidligere :)


Når du skal smide items ind i din listbox..

lbServers.DataSource = xDoc.Root.Element("Servers").Elements("Server")
.Select(x => new Server(x.Element("IP").Value, int.Parse(x.Element("Port").Value), x.Element("MAC").Value, x.Element("ID").Value));

.. håber eg fik alle paranteser korrekt :)
og databind...
lbServers.DataBind();=


pyhh.. blev en lang post...
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



IT-JOB

Metroselskabet og Hovedstadens Letbane

Cyber Security Konsulent

PensionDanmark

Business Tester

Udviklings- og Forenklingsstyrelsen

Generalist til PMO