잊지 않겠습니다.

'Linq'에 해당되는 글 7건

  1. 2009.02.10 System.Reflection을 이용한 Assembly Remote Runner
  2. 2009.01.15 Pro LINQ (07)
  3. 2009.01.13 XmlDocument와 XDocument간의 변환
  4. 2009.01.13 Pro Linq (06)
  5. 2009.01.08 Pro LINQ (03)
  6. 2009.01.07 Pro LINQ (02)
  7. 2009.01.07 Pro LINQ (01)
Unit Test에서 사용되는 NUnit를 보면 [Test] attribute와 [TestFixture] attribute를 이용해서 각각의 Test Class와 Method를 모두 얻어내게 된다.

먼저, Assembly의 Load는 간단하게 Assembly의 static method를 통해서 얻어올 수 있다.

Assembly assem = Assembly.LoadFile(PlugInFileName);

여기에서 Assembly의 각 Class의 Attribute의 조건을 얻어오기 위해서 static class를 하나 생성

public static bool HasAttribute(MemberInfo member, string attrName, bool inherit)
{
    object[] attributes = member.GetCustomAttributes(inherit);
    foreach(Attribute attribute in attributes)
    {
        if(IsInstanceOfType(attrName, attribute))
        {
            System.Diagnostics.Debug.WriteLine(attribute);
            return true;
        }
    }
    return false;
}

얻어진 결과를 linq를 이용해서 검색. (이런 곳에서도 linq는 이용 가능하다. ^^)

var types = from t in assem.GetTypes()
            where Reflect.HasAttribute(t, typeName, true) 
            select t;

이렇게 얻어온 Class를 Activator를 이용해서 Instance를 생성해주면 외부 assembly가 가지고 있는 class의 동적 이용 및 NUnit과 비슷한 동작을 하는 것이 가능해진다. 

ISYNCmailPlugIn plugIn = Activator.CreateInstance(type) as ISYNCmailPlugIn;

Remote에서 사용하게 될 경우에 장점은 다음과 같다. 
1. Compile시에 Dll이 필요하지 않다. 
: 동적 load가 되기 때문에 잦은 변경이 있는 lib인 경우에 사용이 편리하다. 

2. 특정한 Interface나 Attribute를 가지고 있는 경우에 외부에서 사용이 가능하다.
Posted by Y2K
,

Pro LINQ (07)

Book 2009. 1. 15. 02:32
XML Schema(*.xsd)파일을 이용한 XML의 Validation과 기존의 XmlDocument에서 지원되는 XPath 역시 같이 지원 가능하다. 또한, 제공되는 XML을 통한 XML Schema를 역으로 얻어내는 방법을 같이 제공하고 있다. 

var xDocument = new XDocument();
var rootElement = new XElement("BookParticipants");

var bookElement1 = new XElement("BookParticipant");
bookElement1.Add(new XAttribute("type", "Author"));
bookElement1.Add(new XElement("FirstName", "Joe"));
bookElement1.Add(new XElement("LastName", "Rattz"));
rootElement.Add(bookElement1);

var bookElement2 = new XElement("BookParticipant");
bookElement2.Add(new XAttribute("type", "Editor"));
bookElement2.Add(new XElement("FirstName", "Ewan"));
bookElement2.Add(new XElement("LastName", "Buckingham"));
rootElement.Add(bookElement2);

xDocument.Add(rootElement);
xDocument.Save("bookparticipants.xml");

XmlSchemaInference infer = new XmlSchemaInference();
XmlSchemaSet schemaSet = infer.InferSchema(XmlReader.Create("bookparticipants.xml"));
XmlWriter xmlWriter = XmlWriter.Create("bookparticipants.xsd");

foreach(XmlSchema xmlSchema in schemaSet.Schemas())
{
    xmlSchema.Write(xmlWriter);
}
xmlWriter.Close();

XDocument schemaDocument = XDocument.Load("bookparticipants.xsd");
Console.WriteLine(schemaDocument);

정말로 대단한 기능이라고 생각이 되는 것이, XML 파일만 있더라고 그 안에서 XSD의 추론이 가능해지기 때문에, 그 응용을 어떤 방향으로 솔찍히 해줘야지 될지 잘은 모르겠다는 생각이 든다. 아직 XSD를 잘 사용을 안하고 있는 것이 잘 모르고 있는 이유중 하나일 것 같다.

XML의 Validation은 다음과 같이 할 수 있다. 기존의 XmlDocument와 코드가 완전히 동일하다.
XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.Add(string.Empty, "bookparticipants.xsd");
try
{
    xDocument.Validate(schemaSet, null);
    Console.WriteLine("Document validated successfully");
}
catch(XmlSchemaValidationException ex)
{
    Console.WriteLine(ex.Message);
}


마지막으로 XDocument에서의 XPath 사용을 간략한 예이다.
xDocument.Add(rootElement);
XElement xElement = xDocument.XPathSelectElement("//BookParticipants/BookParticipant[FirstName='Joe']");
Console.WriteLine(string.Format("Selected Element : {0} / {1}", xElement.Name, xElement.Value));




Posted by Y2K
,
1. XDocument to XmlDocument
            XDocument xDocument = new XDocument();
            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.Load(xDocument.CreateReader());

2. XmlDocument to XDocument
            StringReader sr = new StringReader(xmlDoc.InnerXml);
            XDocument xDocument = XDocument.Load(XmlReader.Create(sr));


Posted by Y2K
,

Pro Linq (06)

Book 2009. 1. 13. 10:51
LINQ를 이용한 XML의 검색방법 역시 기존의 LINQ와 동일하다. 
특징적으로 이야기할 수 있는 사항은 각각의 XML의 element, attribute, comment 등으로 검색이 가능하다는 점으로, DB LINQ나 Object LINQ에서 사용하는 것과 같이 XML의 특성으로 검색이 가능하다. 

조금 복잡한 LINQ query를 하나 예시로 든다면.. 

            var biddata = from b in bids.Descendants("bid_tuple")
                          where double.Parse(b.Element("bid").Value) > 50
                          join u in users.Descendants("user_tuple")
                              on b.Element("userid").Value equals u.Element("userid").Value
                          join i in items.Descendants("item_tuple")
                              on b.Element("itemno").Value equals i.Element("itemno").Value
                          select new
                                     {
                                         Item = b.Element("itemno").Value,
                                         Description = i.Element("description").Value,
                                         User = u.Element("name").Value,
                                         Date = b.Element("bid_date").Value,
                                         Price = b.Element("bid").Value
                                     };
            foreach(var bd in biddata)
            {
                Console.WriteLine("{0, -12} {1, -12} {2, -6}, {3, -14}, {4:C, 10}", bd.Date, bd.User, bd.Item,
                                  bd.Description, bd.Price);
            }

보면 재미있는 내용중 하나가 select 구문에서의 새로운 Class의 생성이다. 이 Class는 따로 선언되어있지 않으며, 각각의 Property의 이름을 각각 적어서 생성하게 된다. 이 부분은 C# 4.0에서 dynamic programming과 비슷하게 보이지만 dynamic으로 선언된것과는 다르게 사용된다. var로 선언되어 익명 class로 생성된 상태이다. 

여기에서 bd에 대해 type을 얻어보면 다음과 같다.
<>f__AnonymousType1`5[String, String, String, String, String]
사용된 Item, Description, User, Date, Price에 대해서 5개의 Property를 갖는 익명 Class의 선언으로 되어 있는 것을 알 수 있다.
Posted by Y2K
,

Pro LINQ (03)

Book 2009. 1. 8. 00:28
먼저 설명된 select, take 등이 지연된 operation이라면, 모든 Action이 호출즉시 나오게 된다. 이럴 경우에는 LINQ가 가진 속도의 장점을 잃어버리게 된다. 그렇지만 모든 객체를 한번에 얻어와서 일을 처리하게 될 경우에는 보다더 용의하게 된다. 

    public class DataContextLinq
    {
        public void QueryDatas()
        {
            NorthwindDataContext dbContext = new NorthwindDataContext(@"Data Source=Y2K\SQLEXPRESS;Initial Catalog=AdventureWorks;Integrated Security=True");
            dbContext.Log = Console.Out;

            Console.WriteLine("Queried datas - Start");
            var products = (from p in dbContext.Products where p.Color == "Red" select p.Name).ToList();
            Console.WriteLine("Queried datas - End");
            
            Console.WriteLine("Deferred Operation - Start");
            foreach(string productName in products)
            {
                Console.WriteLine(productName);
            }
        }
    }

결과는 다음과 같다. 

차이를 보면, 값을 얻어오는 순간 모든 Query가 실행이 되고, 전 값을 다 얻어오게 된다. 
nondeferred operation은 다음과 같다. 

ToArray()
ToList()
ToDictionary()
ToLookup()
First()
FirstOrDefault()
LastOrDefault()
Single()
SingleOrDefault()
ElementAt()
Sum()
Max()
Min()
etc.... 


경우에 따라 deferred operation과 non-deferred operation의 사용을 달리해줄 필요가 있다. 많은 양의 데이터를 가지고 온다면 deferred operation이 속도 면에서 더 나은 선택이 되지만, 많은 데이터에 대해서 일괄처리를 하게 될 경우에는 non-deferred operation이 선택이 될 수 있다. 











Posted by Y2K
,

Pro LINQ (02)

Book 2009. 1. 7. 18:50
LINQ에서 사용되는 select, where, selectmany는 지연된 동작(deferred operation)을 행한다.

LINQ query가 실행하는 동시에 각 객체를 얻어내고 실행하는 것이 아닌, 결과가 이용될 때에 각각의 객체를 얻어오는 형식이 된다. 

다음과 같은 예제 LINQ query를 보면..
    public class DataContextLinq
    {
        public void QueryDatas()
        {
            NorthwindDataContext dbContext = new NorthwindDataContext(@"Data Source=Y2K\SQLEXPRESS;Initial Catalog=AdventureWorks;Integrated Security=True");
            dbContext.Log = Console.Out;

            Console.WriteLine("Queried datas - Start");
            var products = from p in dbContext.Products where p.Color == "Red" select p;
            Console.WriteLine("Queried datas - End");

            Console.WriteLine("Deferred Operation - Start");
            foreach(Product product in products)
            {
                Console.WriteLine(product.Name);
            }
        }
    }

여기에서 var products = from p in dbContext.Products where p.Color == "Red" select p; 에서 검색이 이루어지는 것이 아닌, 각 객체를 얻어낼 때에 그 Query를 던지게 된다. 결과는 다음과 같다. 



이는 foreach 문에서 기존의 DataReader에서 MoveNext() 구문을 호출하게 되는 것과 동일하게 움직이게 된다. 
또한 값을 처음호출할때, DB에 대한 Connection을 연결하기 때문에, DBContext 객체의 경우에는 생성 및 삭제에서 조금 덜 엄격한 IDispose role을 따르게 된다. 
Posted by Y2K
,

Pro LINQ (01)

Book 2009. 1. 7. 18:13
LINQ(Language-Integrated Query)는 .NET Programmer들에게 프로그램의 개발방향을 새로 만들어줬다고 해도 과언이 아니다. 무엇보다 그전까지 사용하고 있던 모든 DB에 대한 O/R mapping을 쓸데 없게 만들어버린 것 뿐 아니라 모든 데이터에 대한 객체화를 만들 수 있었다는 점에서 LINQ의 위대함이 더 보이는 것 같다. 

검색, 정렬, 다른 객체와의 Join, Grouping 모든 것을 다 LINQ를 통해서 할 수 있다는 점은 LINQ에 대한 매력을 더욱더 가지고 오게 한다. 

먼저 간단한 Hello LINQ 소스를 보면..

    public class HelloLinq
    {
        public void Hello()
        {
            string[] greetings = { "Hello world", "hello LINQ", "Hello Apress" };
            var items = from s in greetings where s.EndsWith("LINQ") select s;

            foreach(string item in items)
            {
                Console.WriteLine(item);
            }
        }
    }

    public class XmlLinq
    {
        public void FindBook()
        {
            XElement books =
                XElement.Parse(
                    @"<books>
                        <book>
                        <title>Pro LINQ: Language Integrated Query in C# 2008</title>
                        <author>Joe Rattz</author>
                        </book>
                        <book>
                        <title>Pro WF: Windows Workflow in .NET 3.0</title>
                        <author>Bruce Bukovics</author>
                        </book>
                        <book>
                        <title>Pro C# 2005 and the .NET 2.0 Platform, Third Edition</title>
                        <author>Andrew Troelsen</author>
                        </book>
                        </books>");
            var titles = from book in books.Elements("book")  
                         where (string)book.Element("author") == "Joe Rattz" select book.Element("title");
            foreach(var title in titles)
            {
                Console.WriteLine(title.Value);
            }
        }
    }

데이터 array, XML, List<object> 모든것에 대한 검색 및 데이터의 selection을 다 할 수 있다. 

흔히, LINQ를 DB에서만 보는 경향이 많은데... (이건 DB Metal의 이유가 가장 클것 같다.) LINQ는 데이터에 대한 검색이라고 할 수 있다. 모든 데이터에 대한. 

LINQ는 다음과 같이 구성되어있다. 

  • LINQ to Object : IEnumerable<T>에 대한 검색 제공
  • LINQ to XML : System.Xml.Linq에서 XML에 대한 LINQ query 검색 제공
  • LINQ to SQL : DB와 연결
  • LINQ to DataSet : ASP .NET 또는 WinForm에서 주로 사용되는 DataSet과의 연결






Posted by Y2K
,