잊지 않겠습니다.

0004. XmlGeneral

Sample Codes 2010. 1. 5. 13:21
xml파일을 각 ElementNode별로 읽고, XmlDocument를 생성하고 저장하는 sample code
XmlDocument에 새로운 Element를 생성하는 것은 생성후에 XmlDocument에 넣는 것이 아니라, XmlDocument를 통해 객체를
생성하고, 생성된 객체에 값을 넣은 이후에 XmlDocument에 Append하는 과정을 거쳐야지 된다는 것을 기억하면 매우 쉬운 소스다.


/****************************** Module Header ******************************\
* Module Name:	Program.cs
* Project:		CSXmlGeneral
* Copyright (c) Microsoft Corporation.
* 
* This C# sample project shows how to read a XML file by using XmlTextReader 
* or XmlNodeReader. It also shows, instead of using forward-only reader, how 
* to read, modify, and update Xml element using the XmlDocument class. This 
* class will load the whole document into memory for modification and we can 
* save the modified XML file to the file system.
* 
* The XML file used by the demo has this format:
* 
* 
*  
*    Gambardella, Matthew
*    XML Developer's Guide
*    Computer
*    44.95
*    2000-10-01
*    
*      An in-depth look at creating applications
*      with XML.
*    
*  
*  
*   ...
*  
* 
* 
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
* All other rights reserved.
* 
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/

#region Using directives
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
#endregion


class Program
{
    static void Main(string[] args)
    {
        /////////////////////////////////////////////////////////////////////
        // Read XML document using the XmlTextReader class.
        // 

        // The XmlTextReader acts as a reader pointer that only moves forward.
        // Because it always moves forward and read a piece of data into 
        // memory buffer, it has better performance than the XmlDocument 
        // class which loads the whole document into memory.

        Console.WriteLine("Loading XML using XmlTextReader...");

        XmlTextReader xmlTextReader = new XmlTextReader(@"Books.xml");
        xmlTextReader.WhitespaceHandling = WhitespaceHandling.None;

        while (xmlTextReader.Read())
        {
            if (xmlTextReader.Name == "book")
            {
                Console.WriteLine(xmlTextReader.GetAttribute("id") + ": ");

                xmlTextReader.Read();
                string author = xmlTextReader.ReadElementContentAsString();
                string title = xmlTextReader.ReadElementContentAsString();
                string genre = xmlTextReader.ReadElementContentAsString();
                string price = xmlTextReader.ReadElementContentAsString();
                string publishDate = xmlTextReader.ReadElementContentAsString();
                string description = xmlTextReader.ReadElementContentAsString();

                Console.WriteLine(genre + " book \"" + title + "\" written by \"" +
                    author + "\", published on " + publishDate);
                Console.WriteLine(description);
            }
        }

        xmlTextReader.Close();


        /////////////////////////////////////////////////////////////////////
        // Read XML document using the XmlDocument and XmlNodeReader classes.
        // 

        // XmlNodeReader is similar to XmlTextReader but accepts an XmlNode 
        // instance as target to read. The following code shows how to use 
        // XmlDocument and XmlNodeReader to retrieve XML information. It is 
        // also a forward-only reader.

        Console.WriteLine("Loading XML using XmlDocument & XmlNodeReader...");

        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.Load(@"Books.xml");
        XmlNodeList xmlNodes = xmlDocument.GetElementsByTagName("book");
        foreach (XmlNode node in xmlNodes)
        {
            Console.WriteLine(node.Attributes["id"].Value + ":");

            XmlNodeReader xmlNodeReader = new XmlNodeReader(node);
            xmlNodeReader.Read();
            xmlNodeReader.Read();
            string author = xmlNodeReader.ReadElementContentAsString();
            string title = xmlNodeReader.ReadElementContentAsString();
            string genre = xmlNodeReader.ReadElementContentAsString();
            string price = xmlNodeReader.ReadElementContentAsString();
            string publishDate = xmlNodeReader.ReadElementContentAsString();
            string description = xmlNodeReader.ReadElementContentAsString();

            Console.WriteLine(genre + " book \"" + title + "\" written by \"" +
                author + "\", published on " + publishDate);
            Console.WriteLine(description);
        }


        /////////////////////////////////////////////////////////////////////
        // Make changes to the XmlDocument.
        // 

        // Modify a node value by first calling SelectSingleNode to navigate 
        // to that node and by setting its InnerText property to change its 
        // content.
        XmlNode nodeToModify = xmlDocument.DocumentElement.SelectSingleNode(
            "book/genre");
        nodeToModify.InnerText = "XML Tech";

        // Add a new XML node. In XML programming, we always call 
        // XMLDocument.Create*** to create an attribute or element. After 
        // that, we can add it into where we want by calling Node.AppendChild
        XmlElement newElement = xmlDocument.CreateElement("book");
        XmlAttribute newAttribute = xmlDocument.CreateAttribute("id");
        newAttribute.Value = "bk103";
        XmlElement authorElement = xmlDocument.CreateElement("author");
        authorElement.InnerText = "Mark Russinovich,David Solomon,Alex Ionecsu";
        XmlElement titleElement = xmlDocument.CreateElement("title");
        titleElement.InnerText = "Windows Internals, 5th edition";
        XmlElement genreElement = xmlDocument.CreateElement("genre");
        genreElement.InnerText = "Windows Server 2008";
        XmlElement priceElement = xmlDocument.CreateElement("price");
        priceElement.InnerText = "69.99";
        XmlElement publishDateElement = xmlDocument.CreateElement("publish_date");
        publishDateElement.InnerText = "2009-6-17";
        XmlElement descriptionElement = xmlDocument.CreateElement("description");
        descriptionElement.InnerText = "Windows Internals, 5th edition is the" +
            " update to Windows Internals, 4th edition to cover Windows Vista" +
            " and Windows Server 2008 (32-bit and 64-bit).";

        newElement.Attributes.Append(newAttribute);
        newElement.AppendChild(authorElement);
        newElement.AppendChild(titleElement);
        newElement.AppendChild(genreElement);
        newElement.AppendChild(priceElement);
        newElement.AppendChild(publishDateElement);
        newElement.AppendChild(descriptionElement);
        xmlDocument.DocumentElement.AppendChild(newElement);

        // Save the changes
        xmlDocument.Save("Modified Books.xml");

        // XmlLDocument does not have Close or Dispose method because it is 
        // an in-memory representation of an XML document. Once read, the 
        // file is no-longer needed.
    }
}



  
    Gambardella, Matthew
    XML Developer's Guide
    Computer
    44.95
    2000-10-01
    
      An in-depth look at creating applications
      with XML.
    
  
  
    Ralls, Kim
    Midnight Rain
    Fantasy
    5.95
    2000-12-16
    
      A former architect battles corporate zombies,
      an evil sorceress, and her own childhood to become queen
      of the world.
    
  

Posted by Y2K
,
.NET에서 Serialization은 객체를 저장하고, 객체를 다시 불러오는데 매우 유용하다. 그리고 네트워크로 Serialization된 객체를 전송하고,
다시 그 객체를 사용할 수 도 있는 .NET에서 핵심적인 기능중 하나이다.

XmlSerialization을 하기 위해 가장 유의할 점은 생성자는 input parameter가 없는 생성자만이 가능하다는 점을 항시 알아야지 된다.
input parameter가 있는 경우에는 Runtime시에 exception이 발생되게 된다.


/****************************** Module Header ******************************\
* Module Name:	Program.cs
* Project:		CSXmlSerialization
* Copyright (c) Microsoft Corporation.
* 
* This sample shows how to serialize an in-memory object to a local xml file 
* and how to deserialize the xml file back to an in-memory object using 
* C#. The designed MySerializableType includes int, string, generic, as well
* as customized type field and property.
* 
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
* All other rights reserved.
* 
* History:
* * 7/29/2009 3:00 PM Colbert Zhou Created
* * 8/20/2009 12:01 AM Jialiang Ge Reviewed
\***************************************************************************/

#region Using directives
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Collections;
#endregion


namespace CSXmlSerialization
{
    class Program
    {
        static void Main(string[] args)
        {
            /////////////////////////////////////////////////////////////////
            // Serialize the object to an XML file.
            // 

            // Create and initialize a MySerializableType instance.
            MySerializableType instance = new MySerializableType();
            instance.BoolValue = true;
            instance.IntValue = 1;
            instance.StringValue = "Test String";
            instance.ListValue.Add("List Item 1");
            instance.ListValue.Add("List Item 2");
            instance.ListValue.Add("List Item 3");
            instance.AnotherTypeValue = new AnotherType();
            instance.AnotherTypeValue.IntValue = 2;
            instance.AnotherTypeValue.StringValue = "Inner Test String";

            // Create the serializer
            XmlSerializer serializer = new XmlSerializer(typeof(MySerializableType));

            // Serialize the object to an XML file
            using (StreamWriter streamWriter = File.CreateText(
                "CSXmlSerialization.xml"))
            {
                serializer.Serialize(streamWriter, instance);
            }


            /////////////////////////////////////////////////////////////////
            // Deserialize from a XML file to an object instance.
            // 

            // Deserialize the object
            MySerializableType deserializedInstance;
            using (StreamReader streamReader = File.OpenText(
                "CSXmlSerialization.xml"))
            {
                deserializedInstance = serializer.Deserialize(streamReader) 
                    as MySerializableType;
            }

            // Dump the object
            Console.WriteLine("BoolValue: {0}", deserializedInstance.BoolValue);
            Console.WriteLine("IntValue: {0}", deserializedInstance.IntValue);
            Console.WriteLine("StringValue: {0}", deserializedInstance.StringValue);
            Console.WriteLine("AnotherTypeValue.IntValue: {0}", 
                deserializedInstance.AnotherTypeValue.IntValue);
            Console.WriteLine("AnotherTypeValue.StringValue: {0}", 
                deserializedInstance.AnotherTypeValue.StringValue);
            Console.WriteLine("ListValue: ");
            foreach (object obj in deserializedInstance.ListValue)
            {
                Console.WriteLine(obj.ToString());
            }
        }
    }


    /// 
    /// Serializable Type Declaration
    /// 
    [Serializable()]
    public class MySerializableType
    {
        // String field and property
        private string stringValue;
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }

        // Bool field and property
        private bool boolValue;
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        // Int field and property
        private int intValue;
        public int IntValue
        {
            get { return intValue; }
            set { intValue = value; }
        }

        // Another type field and property
        private AnotherType anotherTypeValue;
        public AnotherType AnotherTypeValue
        {
            get { return anotherTypeValue; }
            set { anotherTypeValue = value; }
        }

        // Generic type field and property
        private List listValue = new List();
        public List ListValue
        {
            get { return listValue; }
            set { listValue = value; }
        }

        // Ignore a field using NonSerialized attribute
        [NonSerialized()]
        private int ignoredField = 1;
    }

    /// 
    /// Another Type Declaration
    /// 
    [Serializable()]
    public class AnotherType
    {
        private string stringValue;
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }

        private int intValue;
        public int IntValue
        {
            get { return intValue; }
            set { intValue = value; }
        }
    }
}
Posted by Y2K
,

0002. CSXPath

Sample Codes 2010. 1. 5. 13:10
XPathNavigator를 이용해서 Xml 문서를 탐색하고 값을 얻어내는 예제.
특별히 설명될 내용이 없는 간단한 예제이다.

조금 눈 여겨 볼 내용은 XmlDocument를 통해서 생성되는 것이 아닌 XPathDocument를 통해서 XPathNavigator를 생성한다는 점이다.
단순하게 문서를 읽는데에는 XmlDocument나 XDocument를 사용하는 것이 좋으나, xml 파일이 커지거나 xml파일을 일정하게 검색, 변경
할때에는 XPathNavigator를 통해서 검색하는 것이 속도나 코드 면에서 훨씬 좋다.


/****************************** Module Header ******************************\
* Module Name:	Program.cs
* Project:		CSXPath
* Copyright (c) Microsoft Corporation.
* 
* This sample project shows how to use XPathDocument class to load the XML 
* file and manipulate. It includes two main parts, XPathNavigator usage and 
* XPath Expression usage. The first part shows how to use XPathNavigator to 
* navigate through the whole document, read its content. The second part 
* shows how to use XPath expression to filter information and select it out.
* 
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
* All other rights reserved.
* 
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.XPath;


namespace CSXPath
{
    class Program
    {
        static void Main(string[] args)
        {
            #region Initialize XPathDocument and XPathNavigator

            XPathNavigator xPathNavigator;
            XPathDocument xPathDoc;
            
            //Navigate through the whole document
            //Create a new instance of XPathDocument from a XML file
            xPathDoc = new XPathDocument("books.xml");

            //Call CreateNavigator method to create a navigator instance
            //And we will use this navigator object to navigate through whole document
            xPathNavigator = xPathDoc.CreateNavigator();
            
            #endregion

            #region Navigate through the document

            //Move to the root element
            xPathNavigator.MoveToRoot();
            //Catalog element is the first children of the root
            //Move to catalog element
            xPathNavigator.MoveToFirstChild();
            //We can know a XML node's type from the NodeType property
            //XPathNodeType has Attribute, Element, Namespace and so on
            if (xPathNavigator.NodeType == XPathNodeType.Element)
            {
                //We can know if a Node has child nodes by checking its
                //HasChildren property. If it returns true, that node has
                //child nodes
                if (xPathNavigator.HasChildren == true)
                {
                    //Move to the first child which is our first book nodes
                    xPathNavigator.MoveToFirstChild();
                    do
                    {
                        //We can know if a node has any attribute by checking
                        //the HasAttributes property. When this property returns
                        //true, we can get the specified attribute by calling
                        //navigator.GetAttribute() method
                        if (xPathNavigator.HasAttributes == true)
                        {
                            Console.WriteLine("Book ID: " + xPathNavigator.GetAttribute("id", ""));
                        }

                        //Iterate through a book node's child nodes
                        //and list all child node information, like 
                        //name, author, price, publish date and so on
                        if (xPathNavigator.HasChildren)
                        {
                            xPathNavigator.MoveToFirstChild();
                            do
                            {
                                Console.Write("\t{0}:\t{1}\r\n", xPathNavigator.Name, xPathNavigator.Value);
                            } while (xPathNavigator.MoveToNext());
                            //When all child nodes are reached. The MoveToNext() method returns
                            //false. Then we need to call MoveToParent to go back to the book level
                            xPathNavigator.MoveToParent();
                        }
                        //Move to the next book element.
                    } while (xPathNavigator.MoveToNext());
                }
            }

            #endregion

            #region Use of XPath Expression
            
            //Use XPath Expression to select out book bk103
            //The expression should be "/catalog/book[@id='bk103']"
            //@ means to look id attribute and match bk103
            Console.WriteLine("Use XPath Expression to select out the book with ID bk103:");
            XPathExpression expression = xPathNavigator.Compile("/catalog/book[@id='bk103']");
            XPathNodeIterator iterator = xPathNavigator.Select(expression);

            //After compile the XPath expression, we can call navigator.Select
            //to retrieve the XPathNodeIterator. With this interator, we can loop
            //trough the results filtered by the XPath expression
            //The following codes print the book bk103's detailed information
            
            while (iterator.MoveNext())
            {
                XPathNavigator nav = iterator.Current.Clone();
                Console.WriteLine("Book ID: " + nav.GetAttribute("id", ""));
                if (nav.HasChildren)
                {
                    nav.MoveToFirstChild();
                    do
                    {
                        Console.Write("\t{0}:\t{1}\r\n", nav.Name, nav.Value);
                    } while (nav.MoveToNext());
                }
            }


            //Use XPath to select out all books whose price are more than 10.00
            // '[]' means to look into the child node to match the condition "price > 10"
            Console.WriteLine("\r\nUse XPath Expression to select out all books whose price are more than 10:");
            expression = xPathNavigator.Compile("/catalog/book[price>10]");
            iterator = xPathNavigator.Select(expression);

            //After getting the iterator, we print title and price for books 
            //whose price are more than 10
            while (iterator.MoveNext())
            {
                XPathNavigator nav = iterator.Current.Clone();
                Console.WriteLine("Book ID: " + nav.GetAttribute("id", ""));
                if (nav.HasChildren)
                {
                    nav.MoveToFirstChild();
                    do
                    {
                        if (nav.Name == "title")
                        {
                            Console.Write("\t{0}:\t{1}\r\n", nav.Name, nav.Value);
                        }
                        if (nav.Name == "price")
                        {
                            Console.Write("\t{0}:\t{1}\r\n", nav.Name, nav.Value);
                        }
                    } while (nav.MoveToNext());
                }
            }

            //Use XPath Expression to calculate the average price of all books.
            //Here in XPath, we use the sum, div, and count formula.
            Console.WriteLine("\r\nUse XPath Expression to calculate the average price of all books:");
            expression = xPathNavigator.Compile("sum(/catalog/book/price) div count(/catalog/book/price)");
            string averagePrice = xPathNavigator.Evaluate(expression).ToString();
            Console.WriteLine("The average price of the books are {0}", averagePrice);


            #endregion

            #region End. Read a char to exit

            Console.WriteLine("Input any key to quit the sample application");
            Console.ReadLine();

            #endregion
        }
    }
}



  
    Gambardella, Matthew
    XML Developer's Guide
    Computer
    44.95
    2000-10-01
    
      An in-depth look at creating applications
      with XML.
    
  
  
    Ralls, Kim
    Midnight Rain
    Fantasy
    5.95
    2000-12-16
    
      A former architect battles corporate zombies,
      an evil sorceress, and her own childhood to become queen
      of the world.
    
  
  
    Corets, Eva
    Maeve Ascendant
    Fantasy
    5.95
    2000-11-17
    
      After the collapse of a nanotechnology
      society in England, the young survivors lay the
      foundation for a new society.
    
  
  
    Corets, Eva
    Oberon's Legacy
    Fantasy
    5.95
    2001-03-10
    
      In post-apocalypse England, the mysterious
      agent known only as Oberon helps to create a new life
      for the inhabitants of London. Sequel to Maeve
      Ascendant.
    
  
  
    Corets, Eva
    The Sundered Grail
    Fantasy
    5.95
    2001-09-10
    
      The two daughters of Maeve, half-sisters,
      battle one another for control of England. Sequel to
      Oberon's Legacy.
    
  
  
    Randall, Cynthia
    Lover Birds
    Romance
    4.95
    2000-09-02
    
      When Carla meets Paul at an ornithology
      conference, tempers fly as feathers get ruffled.
    
  
  
    Thurman, Paula
    Splish Splash
    Romance
    4.95
    2000-11-02
    
      A deep sea diver finds true love twenty
      thousand leagues beneath the sea.
    
  
  
    Knorr, Stefan
    Creepy Crawlies
    Horror
    4.95
    2000-12-06
    
      An anthology of horror stories about roaches,
      centipedes, scorpions  and other insects.
    
  
  
    Kress, Peter
    Paradox Lost
    Science Fiction
    6.95
    2000-11-02
    
      After an inadvertant trip through a Heisenberg
      Uncertainty Device, James Salway discovers the problems
      of being quantum.
    
  
  
    O'Brien, Tim
    Microsoft .NET: The Programming Bible
    Computer
    36.95
    2000-12-09
    
      Microsoft's .NET initiative is explored in
      detail in this deep programmer's reference.
    
  
  
    O'Brien, Tim
    MSXML3: A Comprehensive Guide
    Computer
    36.95
    2000-12-01
    
      The Microsoft MSXML3 parser is covered in
      detail, with attention to XML DOM interfaces, XSLT processing,
      SAX and more.
    
  
  
    Galos, Mike
    Visual Studio 7: A Comprehensive Guide
    Computer
    49.95
    2001-04-16
    
      Microsoft Visual Studio 7 is explored in depth,
      looking at how Visual Basic, Visual C++, C#, and ASP+ are
      integrated into a comprehensive development
      environment.
    
  

Posted by Y2K
,
CodePlex에서 진행되고 있는 All-In-One Code Framework 소개 (http://cfx.codeplex.com/wikipage?title=All-In-One%20Code%20Framework%20Examples&ProjectName=cfx)

xml파일을 xsl 형식을 이용해서 converting 하는 예제코드.
System.Xml.Xsl.XslCompiledTransform를 이용해서 converting 하는 간단한 예제를 보이고 있다.


 


  
    Gambardella Matthew
    XML Developer's Guide
    Computer
    44.95
    2000-10-01
    An in-depth look at creating applications with XML.
  
  
    Ralls Kim
    Midnight Rain
    Fantasy
    5.95
    2000-12-16
    A former architect battles corporate zombies and her own childhood to become queen of the world.
  
  
    Corets Eva
    Maeve Ascendant
    Fantasy
    5.95
    2000-11-17
    After the collapse of a nanotechnology society in England the young survivors lay the foundation for a new society.
  
  
    Corets Eva
    Oberon's Legacy
    Fantasy
    5.95
    2001-03-10
    In post-apocalypse England the mysterious agent known only as Oberon helps to create a new life for the inhabitants of London. Sequel to Maeve Ascendant.
  
  
    Corets Eva
    The Sundered Grail
    Fantasy
    5.95
    2001-09-10
    The two daughters of Maeve half-sisters battle one another for control of England. Sequel to Oberon's Legacy.
  
  
    Randall Cynthia
    Lover Birds
    Romance
    4.95
    2000-09-02
    When Carla meets Paul at an ornithology conference tempers fly as feathers get ruffled.
  
  
    Thurman Paula
    Splish Splash
    Romance
    4.95
    2000-11-02
    A deep sea diver finds true love twenty thousand leagues beneath the sea.
  
  
    Knorr Stefan
    Creepy Crawlies
    Horror
    4.95
    2000-12-06
    An anthology of horror stories about roaches centipedes scorpions  and other insects.
  
  
    Kress Peter
    Paradox Lost
    Science Fiction
    6.95
    2000-11-02
    After an inadvertant trip through a Heisenberg Uncertainty Device James Salway discovers the problems of being quantum.
  
  
    O'Brien Tim
    Microsoft .NET: The Programming Bible
    Computer
    36.95
    2000-12-09
    Microsoft's .NET initiative is explored in detail in this deep programmer's reference.
  
  
    O'Brien Tim
    MSXML3: A Comprehensive Guide
    Computer
    36.95
    2000-12-01
    The Microsoft MSXML3 parser is covered in detail with attention to XML DOM interfaces XSLT processing SAX and more.
  
  
    Galos Mike
    Visual Studio 7: A Comprehensive Guide
    Computer
    49.95
    2001-04-16
    Microsoft Visual Studio 7 is explored in depth looking at how Visual Basic/Visual C++/C#/ASP+ are integrated into a comprehensive development environment.
  



    
    
      
    
    
      "
      
      "
      
      
        "
        
        "
        
          
        
      
      


    


#region Using directives
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Xsl;
#endregion


namespace CSXslTransformXml
{
    class Program
    {
        static void Main(string[] args)
        {
            XslCompiledTransform transform = new XslCompiledTransform();
            transform.Load("Books.xslt");
            transform.Transform("Books.xml", "Books.csv");
        }
    }
}
Posted by Y2K
,
설치 이후.. 이상할 정도로 UI가 전보다 빠르다.;

Win7에 최적화가 되어있나? 라는 생각도 들고. UI쪽에 실버라이트와 DirectX 기술이 들어가있다는 말은 들었는데. 그것 때문인가 라는 생각도 들고.;

무엇보다 설치 이후에 충격적인 내용은..;;

다음과 같은 코드 실행의 결과가 아래와 같이 나왔다는 점이다.;


class Program
{
static void Main(string[] args)
{
string runtimeEnvironment = RuntimeEnvironment.GetRuntimeDirectory();
Console.WriteLine(runtimeEnvironment);
}
}


CLR의 버젼이 완전히 바뀌었다.;;; 3.x대를 완전히 넘어가서 바로 4.0.21 대로 진입.
.NET Framework의 새로운 장이 열렸다고 해도 과언이 아닌 변화가 이루어졌다;;

Powershell과의 통합은 어찌된걸까?; 다른 .NET과의 통합은? ;;;
Posted by Y2K
,
1. IIS
* IIS의 pipe line mode
> ISAPI mode : class mode라고도 불리우며, 이는 file의 확장자를 기준으로 ISAPI 확장에 의하여 처리된다.
> Integrated mode : .NET이 pipe line의 일부이기 때문에 특정 file의 확장자와 관련된 어떠한 ISAPI mode가 필요하지 않는다.

System.Web.Routing.UrlRoutingModule 에 의하여 Url의 Routing이 처리가 된다.
이는 Url의 모든 파일이나 내용이 .NET에 의하여 관리되는 것을 의미한다.

2. Routing
System.Web.Routing.UrlRoutingModule은 요청을 받는 즉시 System.Web.Routing을 실행한다.
Routing의 역활은 먼저, Disk의 파일과의 연관성을 찾아내고 파일과의 연관성이 없는 경우, URL 패턴을 인식하고 분석하여 내부 Component가 사용할 수 있는 Request context 데이터 구조를 구성한다. 파일과의 연관성이 발견되는 경우, 파일에 대하여 실행이 되게 된다. 정적 resource 파일들(*.jpg와 같은 그림 파일이나 html 파일들)에 대하여 제공 및 aspx 파일에 대한 WebForm 실행이 이루어진다.
Routing 구성은 System.Web.Routing.RouteTable이라는 static collection안에 놓여진다. 그 Collection안의 entry는 서로 다른 URL pattern을 표현하는데 이 부분의 경우에는 Global.asax 파일안에 RegisterRoutes() method로 사용자가 구성이 가능하다.

3. Controller & Action
기본적으로 MvcRouteHandler라는 Routing 처리기를 이용해서 구성이 되며, Routing 결과에 따라 ControllerFactory에서 Controller를 생성하게 된다. 이 과정에서 MvcRouterHandler는 MVC Controller를 찾아내고, Action method의 매개변수를 제공한다. 이 과정은 Assembly reflection을 이용하고 있으며 모든 IController interface를 가지고 이름이 *Controller로 끝이 나는 모든 public class를 ControllerFactory에 등록하고, 들어온 URL 결과에 따라 특정 Controller를 실행하고, 그에 맞는 Action method를 실행한다. 따라서, Controller에서 직접 Response를 제어할 수 있으나, MVC에서는 이를 권장하지 않는다. MVC에서는 계획된 출력을 의미하는 ActionResult 객체를 반환하는 것이 권장된다.

4. ActionResult & View
Controller에서 제공된 ActionResult를 이용하여 View를 Render하는 과정이다. 기본적으로 View의 Render는 IViewEngine을 구현하는 .NET class를 통해서 구현되는데 기본적으로 WebFormViewEngine을 사용한다. 이름을 보면 알 수 있듯이 이는 기존의 WebForm이 Render 될 때 사용되는 View Engine과 동일하다. 그러나 MVC의 '관계의 분리' 개념에 따라 View는 HTML을 생성하는 것 이외에는 어떠한 일을 하지 않는다.
 

Posted by Y2K
,
.NET MVC 및 모든 Component Model에서 Entry의 에러를 표시하는데 사용되는 Interface.
인터페이스는 각 Property에 대한 값을 검사할 수 있도록 this[columnName]에 대한 정의와 객체의 에러 상태를 알아볼 수 있는 Error 라는 string property를 지원한다.

여기에서 각 에러값은 null이 반환될 때, 에러가 없다고 가정이 되며, String.Empty가 반환되는 경우에도 에러라고 인식하게 된다.(ASP.NET MVC)

사용예는 다음과 같다.

[Table(Name="Product")]
public class Product : IDataErrorInfo 
{
    [Column(IsPrimaryKey=true, IsDbGenerated=true, AutoSync=AutoSync.OnInsert)]
    public int ProductId { get; set; }
    [Column]
    public string Name { get; set; }
    [Column]
    public string Description { get; set; }
    [Column]
    public decimal Price { get; set; }
    [Column]
    public string Category { get; set; }

    #region IDataErrorInfo Members

    public string Error
    {
        get { return null; }
    }

    public string this[string columnName]
    {
        get
        {
            if((columnName == "Name") && string.IsNullOrEmpty(Name))
                return "Please enter a product name";
            if((columnName == "Description") && string.IsNullOrEmpty(Description))
                return "Please enter a description";
            if((columnName == "Price") && (Price <= 0))
                return "Price must not be negative or zero";
            if((columnName == "Category") && string.IsNullOrEmpty(Category))
                return "Please specify a category";
            return null;
        }
    }

    #endregion
}
Posted by Y2K
,
복불복이나 사다리타기 같은 프로그램을 간단히 만들어보자라는 생각으로 잡았다가 은근히 일이 커져버렸다.;
Random으로 어떻게하면 뽑아낼 수 있을지, 요즘 고민되고 있는 Domain-Driven 방법을 어떻게하면 적용할 수 있을지를 고민하다가,
별것도 아닌것에 시간을 다 잡아먹어버린것 같다.;

ASP .NET MVC에서 AJAX도 사용해보고, Castle container도 사용해보고.. 이것저것 사용해보면서 재미를 느낀 짬짬이 취미생활.;

Domain Model 구성은 다음과 같다. 데이터를 따로 제공하지 않아도 되어서 Repository는 비어있는 상태


핵심이된 List Shuffle method.
    static class ShuffledList
    {
        public static List Shuffle(this List list)
        {
            string[] shuffledList = new string[list.Count];
            List freeIndex = new List();
            Random rand = new Random();

            for(int i = 0 ; i < list.Count ; i++)
            {
                freeIndex.Add(i);
            }

            foreach(string item in list)
            {
                int indexOfNewIdx = rand.Next(freeIndex.Count);
                int newIdxOfCard = freeIndex[indexOfNewIdx];

                shuffledList[newIdxOfCard] = item;
                freeIndex.Remove(newIdxOfCard);
            }
            return shuffledList.ToList();
        }
    }



Domain-Driven으로 3tier로 작성해주면서.. 참 이렇게 편하고 좋은 방법을 내가 돌아가고 있었구나.. 하는 후회가 엄청나게 된다.
많은 것을 더 배워야지 되는데. 나태해진 내 자신도 반성이 되고 말이야.;
Posted by Y2K
,

Castle IoC Component

.NET Framework 2009. 12. 27. 21:29
Domain-Driven Model의 구현에 있어서, Repository와 Service를 각기 달리 구현하는 것은 매우 중요한 문제이다.
Service를 구현한 Repository가 변경되어도 언제나 동일한 서비스가 구현이 가능해야지 되며, 이는 데이터의 저장소나 서비스의 구현을
달리 나눈다는 점에서 테스트의 유용성에도 많은 영향을 미치게 된다. 무엇보다 이 둘이 결합되어 있으면 테스트를 행하는 것이 거의 불가능하다.

테스트를 어떻게 하면 좋게 할 수 있을지에 대한 꽤나 좋은 솔루션으로 castle을 찾게 되었다.

castle은 web.config나 xml 파일로 지정된 component를 기반으로 그 프로젝트에서 사용될 service를 정의하고, 제공해주는 역활을 하고 있으며,
이를 이용해서 단순히 config 파일만 변경하는 것으로 각기 다른 Repository가 제공되는 프로젝트를 만드는 것이 가능하다.

예를 들어 Interface가 다음과 같이 정의된 Repository들이 있을 때에,

namespace DomainModel.Abstract
{
    public interface IProductRepository
    {
        IQueryable Products { get; }
    }
    public interface IShippingDetailRepository
    {
        IQueryable ShippingDetails { get;}
        bool AddShippingDetail(ShippingDetail shippingDetail);
    }
}

이를 이용한 Service Repository는 castle에서 다음과 같이 선언될 수 있다.

	
		
			
				
					Data Source=HOME-PC\SQLEXPRESS;Initial Catalog=SportsStore;Integrated Security=True;Pooling=False
				
			
      
        
      
      
        
          Data Source=HOME-PC\SQLEXPRESS;Initial Catalog=SportsStore;Integrated Security=True;Pooling=False
        
      
			
		
	

위와 같은 Domain-Driven model에서는 가장 중요한 것이 서비스와 데이터간의 완벽한 분리이다.
어떤 식으로 구현해주는 것이 좋은지에 대해서 좀더 많은 생각과 좀더 많은 공부가 필요하다. -_-;;
Posted by Y2K
,
Mockup class를 이용한 Routing test code
URL 테스트는 Rest 및 개발에서 가장 중요한 사항중 하나인데. 테스트코드보다 직접 실행해서 한번 테스트해보는 경우가 더 많은 것 같다.;



private string GetOutboundUrl(object routeValues)
{
    // Get route configuration and mock request context
    RouteCollection routes = new RouteCollection();
    MvcApplication.RegisterRoutes(routes);
    var mockHttpContext = new Moq.Mock();
    var mockRequest = new Moq.Mock();
    var fakeResponse = new FakeResponse();
    mockHttpContext.Setup(x => x.Request).Returns(mockRequest.Object);
    mockHttpContext.Setup(x => x.Response).Returns(fakeResponse);
    mockRequest.Setup(x => x.ApplicationPath).Returns("/");
    // Generate the outbound URL
    var ctx = new RequestContext(mockHttpContext.Object, new RouteData());
    return routes.GetVirtualPath(ctx, new RouteValueDictionary(routeValues)).VirtualPath;
}

이 code를 이용한 test code는 다음과 같이 적을 수 있다.
[Test]
public void Football_Page1_Is_At_Slash_Football()
{
    Assert.AreEqual("/Football", GetOutboundUrl(new
    {
        controller = "Product",
        action = "List",
        category = "Football",
        page = 1
    }));
}

URL의 테스트가 꼭 필요하긴 한데.. 요즘들어 일을 이런쪽으로 전혀 안하고 있다는 아쉬움이 많이 들고 있는듯.;
Posted by Y2K
,