简体   繁体   中英

More elegant/efficient way of doing this? (XML/Linq/Read & Write)

So I have this code right, and it basically reads an XML file and does a few if's to check some things and then places appropriate Controls onto the Canvas (Panel).

But it's very long. Or, longer than I'd like it to be. And this code is like... 2 or 3 years old now.

What I want to do, is use Linq to XML.

Reading from XML File:

OpenFileDialog o = new OpenFileDialog();

            o.Filter =
                "wordreplaced Multimedia Format (*.mf)|*.mf|" +
                "Word Document (*.docx)|*.docx|" +
                "PDF Document (*.pdf)|*.pdf|" +
                "Text FIle (*.txt)|*.txt";
            o.Title = "wordreplaced 11 - Open Document";

            using (o)
            {
                if (o.ShowDialog() == DialogResult.OK)
                {
                    foreach (var controlTag in XDocument.Load(o.FileName).Root.Elements())
                    {
                        var controlType = Type.GetType(
                            string.Format(
                            "System.Windows.Forms.{0}, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
                            controlTag.Name.LocalName), false);
                        if (controlType == null || !typeof(Control).IsAssignableFrom(controlType))
                        {
                            continue;
                        }

                        var control = (Control)Activator.CreateInstance(controlType);
                        control.Text = controlTag.Attributes("Content").First().Value;

                        try
                        {
                            control.ForeColor = Color.FromArgb(
                                int.Parse(controlTag.Attributes("A").First().Value),
                                int.Parse(controlTag.Attributes("R").First().Value),
                                int.Parse(controlTag.Attributes("G").First().Value),
                                int.Parse(controlTag.Attributes("B").First().Value));

                            Font font = FromString(controlTag.Attributes("Font").First().Value);
                            control.Font = font;
                        }
                        catch { continue; }

                        control.BackColor = Color.Transparent;

                        control.MouseDown += new MouseEventHandler(control_MouseDown);
                        control.MouseMove += new MouseEventHandler(control_MouseMove);
                        control.MouseUp += new MouseEventHandler(control_MouseUp);
                        control.MouseClick += new MouseEventHandler(control_MouseClick);
                        control.MouseDoubleClick += new MouseEventHandler(control_MouseDoubleClick);

                        string boldness = Convert.ToString(controlTag.Attributes("Bold"));

                        if (boldness == "yeah")
                            control.Font = new Font(control.Font.Name, control.Font.Size, FontStyle.Bold);
                        Type t = control.GetType();
                        if (t.Name == "Label")
                        {
                            Label label = (Label)control;
                            label.AutoSize = true;
                            label.Location = new Point(
                                Convert.ToInt32(controlTag.Attributes("LocationX").First().Value),
                                Convert.ToInt32(controlTag.Attributes("LocationY").First().Value));


                            Canvas.Controls.Add(label);

                            // handlers.
                            label.MouseDown += new MouseEventHandler(label_MouseDown);
                            label.MouseMove += new MouseEventHandler(label_MouseMove);
                            label.MouseUp += new MouseEventHandler(label_MouseUp);
                            label.MouseClick += new MouseEventHandler(label_MouseClick);
                            label.MouseDoubleClick += new MouseEventHandler(label_MouseDoubleClick);
                        }
                        else if (t.Name == "LinkLabel")
                        {
                            control.Tag = controlTag.Attributes("Address").First().Value;
                            LinkLabel link = (LinkLabel)control;
                            link.AutoSize = true;
                            link.Location = new Point(
                                Convert.ToInt32(controlTag.Attributes("LocationX").First().Value),
                                Convert.ToInt32(controlTag.Attributes("LocationY").First().Value));

                            if (boldness == "yeah")
                                control.Font = new Font(control.Font.Name, control.Font.Size, FontStyle.Bold);

                            link.LinkColor = Color.White;

                            Canvas.Controls.Add(link);

                            // Add handlers.
                            link.MouseDown += new MouseEventHandler(link_MouseDown);
                            link.MouseMove += new MouseEventHandler(link_MouseMove);
                            link.MouseUp += new MouseEventHandler(link_MouseUp);
                            link.MouseClick += new MouseEventHandler(link_MouseClick);
                            link.MouseDoubleClick += new MouseEventHandler(link_MouseDoubleClick);
                        }
                        else if (t.Name == "PictureBox")
                        {
                            PictureBox p = (PictureBox)control;
                            p.Image = Base64ToImage(controlTag.Attributes("Content").First().Value);
                            p.AutoSize = true;
                            p.Location = new Point(
                                Convert.ToInt32(controlTag.Attributes("LocationX").First().Value),
                                Convert.ToInt32(controlTag.Attributes("LocationY").First().Value));

                            Canvas.Controls.Add(p);

                            // Add handlers.
                            p.MouseDown += new MouseEventHandler(p_MouseDown);
                            p.MouseMove += new MouseEventHandler(p_MouseMove);
                            p.MouseUp += new MouseEventHandler(p_MouseUp);
                            p.MouseClick += new MouseEventHandler(p_MouseClick);
                            p.MouseDoubleClick += new MouseEventHandler(p_MouseDoubleClick);
                        }
                    }
                    this.Text = "wordreplaced 11 - " + o.FileName;
                }
            }

Writing to XML File:

            SaveFileDialog s = new SaveFileDialog();

            s.Filter =
                "wordReplaced Multimedia Format (*.mf)|*.mf|" +
                "Word Document (*.docx)|*.docx|" +
                "PDF Document (*.pdf)|*.pdf|" +
                "Text FIle (*.txt)|*.txt";
            s.Title = "wordReplaced 11 - Save Document";
            s.CheckFileExists =
                false;
            XElement d;

            using (s)
            {
                if (s.ShowDialog() == DialogResult.OK)
                {
                    if (File.Exists(s.FileName))
                        d = XElement.Load(s.FileName);
                    else
                        d = new XElement("cs");

                    foreach (Control control in Canvas.Controls)
                    {
                        Type t = control.GetType();

                        switch (t.Name)
                        {
                            case "JTS.TextBox":
                                XElement xe0 = new XElement("JTS.TextBox",
                                    new XAttribute("Content", control.Text),
                                    new XAttribute("LocationX", control.Location.X),
                                    new XAttribute("LocationY", control.Location.Y),
                                    new XAttribute("A", control.ForeColor.A),
                                    new XAttribute("R", control.ForeColor.R),
                                    new XAttribute("G", control.ForeColor.G),
                                    new XAttribute("B", control.ForeColor.B),
                                    new XAttribute("Font", control.Font),
                                    new XAttribute("Bold", "yeah"));
                                d.Add(xe0);
                                break;
                            case "LinkLabel":
                                LinkLabel ll = (LinkLabel)control;

                                try
                                {
                                    XElement xe1 = new XElement("LinkLabel",
                                        new XAttribute("Content", control.Text),
                                        new XAttribute("LocationX", control.Location.X),
                                        new XAttribute("LocationY", control.Location.Y),
                                        new XAttribute("A", ll.LinkColor.A),
                                        new XAttribute("R", ll.LinkColor.R),
                                        new XAttribute("G", ll.LinkColor.G),
                                        new XAttribute("B", ll.LinkColor.B),
                                        new XAttribute("Font", ll.Font),
                                        new XAttribute("Address", control.Tag),
                                        new XAttribute("Bold", "yeah"));
                                    d.Add(xe1);
                                }
                                catch
                                {
                                    XElement xe1 = new XElement("LinkLabel",
                                        new XAttribute("Content", control.Text),
                                        new XAttribute("LocationX", control.Location.X),
                                        new XAttribute("LocationY", control.Location.Y),
                                        new XAttribute("A", ll.LinkColor.A),
                                        new XAttribute("R", ll.LinkColor.R),
                                        new XAttribute("G", ll.LinkColor.G),
                                        new XAttribute("B", ll.LinkColor.B),
                                        new XAttribute("Font", ll.Font),
                                        new XAttribute("Bold", "yeah"));
                                    d.Add(xe1);
                                }

                                break;
                            case "PictureBox":
                                PictureBox px = (PictureBox)control;
                                string ie = ImageToBase64(px.InitialImage, System.Drawing.Imaging.ImageFormat.Bmp);

                                XElement xe2 = new XElement("PictureBox",
                                    new XAttribute("Content", ie),
                                    new XAttribute("LocationX", px.Location.X),
                                    new XAttribute("LocationY", px.Location.Y));
                                d.Add(xe2);
                                break;
                            default:
                                break;
                        }
                        d.Save(s.FileName);

                        FilePath = s.FileName;
                        Text = s.FileName;

                        ds = true;
                    }
                }
            }

Which works fine. Haven't had a single problem with it. But it's just such a mess to try to extend/work with etc. I am in need of a more efficient/cleaner/elegant way to write to, and read from XML files and perform linq queries against them.

I've read a few tutorials, and an article but I didn't quite get it. One website mentioned a StreamWriter, which didn't make any sense, and there seems to be many different ways to write to/read from an XML file with Linq, and it's all very confusing to me.

Any help at all is greatly appreciated,

Thank you

I think your problem is much less using the wrong classes or tools, and much more that you need to learn how to extract methods and stop repeating code in that way.

Ideally the first code should read something like:

// In whatever method loads the file
string fileName = GetFileNameFromUser();
if (fileName != null)
{
    var rootElement = GetRootElementOfXmlFile(fileName);
    foreach (var controlTag in rootElement)
    {
        ProcessControlTag(controlTag);
    }
}

private static void ProcessControlTag(XElement controlTag)
{
    var type = GetControlType(controlTag);
    if (type == null)
    {
        return;
    }

    var control = CreateControl(controlType, controlTag);
    Canvas.Controls.Add(control);
}

private static void CreateControl(Type controlType, XElement controlTag)
{
    var control = (Control)Activator.CreateInstance(controlType);
    AddCommonControlModifications(control, controlTag);

    if (controlType.Name == "Label")
    {
        AddLabelModifications(control, controlTag);
    }
    else if (controlType.Name == "LinkLabel")
    {
        AddLinkLabelModifications(control, controlTag);
    }
    else if (controlType.Name == "PictureBox")
    {
        AddPictureBoxModifications(control, controlTag);
    }
}

and that's just to get you started; I didn't implement several of those methods. Any time you have repeated code (eg the location setting code, or whatever's going on that makes you repeat code twice inside the try/catch), you can extract that into a method.

Methods should generally be 3--5 lines long, not dozens. Break things down into small, reusable, and most importantly readable chunks that declare their intentions with clear names, so that your code reads more like your thought process and less like a long series of magical incantations that somehow make the computer do what you want it to do.

Code works? Do you have any new requirements to implement? Do you have nothing more important to do?

If it ain't broke, don't fix it. You're just going to introduce bugs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM