'GET'에 해당되는 글 32건

  1. 2009.10.06 DI (Dependency Injection) 관련 프레임워크.
  2. 2009.10.06 [맛보기]AJAX 따라하기.
  3. 2009.10.06 방랑이가 생각하는 Spring.NET...
  4. 2009.09.30 Spring.NET - 레퍼런스 문서 한글화 사이트..
  5. 2009.09.30 객체의 생명주기
  6. 2009.09.30 Spring 컨테이너와 아키텍처 구성
  7. 2009.09.30 Spring.NET 생명 주기
  8. 2009.09.30 prototype 패턴 (쌍둥이) 과 singleton 패턴
  9. 2009.09.30 singleton pattern 싱글톤 패턴
  10. 2009.09.29 Hands-on Labs for EL 4.1 and Unity 1.2
  11. 2009.09.24 간단 invoke, casting Sample -1 ... & 필드, 프로퍼티, 메소드
  12. 2009.09.24 string 으로 동적 참조 2 & System.Activator.CreateInstance
  13. 2009.09.24 참고 사이트.
  14. 2009.09.24 간단 예제.
  15. 2009.09.24 * Conditional 어트리뷰트 사용
  16. 2009.09.24 * DllImport 어트리뷰트
  17. 2009.09.24 Attrubute(어트리뷰트)
  18. 2009.09.24 Attribute Oriented Programming
  19. 2009.09.24 [LAST] Sample-3 xml->class & config 파일 연동
  20. 2009.09.24 AOP [Aspect Oriented Programming]
  21. 2009.09.24 [XSD.EXE] XML <->CLASS & Serialization
  22. 2009.09.23 XML 제어 - 읽기......
  23. 2009.09.23 CONFIG XML 의 Element 와 Attribute 를 XPATH 로 값 가져오는 방법
  24. 2009.09.23 Sample-2 .. 예제파일들과 호출..여러 가지것들
  25. 2009.09.23 사용자가 임의로 만든 any XML configuration file 제어 1
  26. 2009.09.23 Unity Application Block 에서의 Configuration 1
  27. 2009.09.23 Error 처리
  28. 2009.09.23 Config 의 type 과 DLL 과 연결 관련...
  29. 2009.09.23 Sample - 1
  30. 2009.09.23 XML Config 제어하기.
posted by 방랑군 2009. 10. 6. 16:47



DI (Dependency Injection)은 크게 보면 객체간 의존성을 객체에게 맡기는 것이 아니라, 컨테이너가 필요한 시점에 필요한 관련 객체를 만들어 의존성을 해소시켜주는 것이며, 이 과정에서 자연스럽게 생성한 객체들의 라이프 싸이클을 관리하는 기능도 제공하게 된다. 따라서 DI 컨테이너를 사용할 경우에는 이를 사용하지 않을 때에 비해 성능상 약간의 영향을 받게 된다. DI 컨테이너를 사용치 않았을 때는, 다른 객체를 필요로하는 주체가 필요한 객체의 생성자를 직접 호출하여 사용하였기 때문에 직관적이며 이렇게 생성된 코드는 다른 사람이 이해할 때 훨씬 쉬운 면이 있다. DI 컨테이너가 개입되면 객체 생성이 간접적으로 이루어지기 때문에 성능상 약간의 오버헤드도 감안해야 하며, 컨테이너 자체에 대한 교육이나 이해가 필요하게 되어  전반적으로 프로젝트의 복잡도는 약간 증가하게 된다. 따라서, 유행처럼 DI 컨테이너에 대한 관심이 증가하고 있지만, 개발하는 프로그램의 성격상 객체간 의존성이 많지 않고, 의존성이 있다손 치더라도 그다지 복잡하지 않은 경우에는 DI 컨테이너의 사용은 추천할만한 것이 못된다. 객체간 혹은 클래스가 의존성이 많고 복잡하며 이의 해소를 컨테이너에 의지하여 추상화하고자 할때 혹은 런타임시에 이들 객체간 의존성을 변경할 필요가 있을 시에는 Unity와 같은 DI 컨테이너의 적용을 고려해볼 만 하다.

'GET > FrameWork' 카테고리의 다른 글

방랑이가 생각하는 Spring.NET...  (0) 2009.10.06
Spring.NET - 레퍼런스 문서 한글화 사이트..  (0) 2009.09.30
객체의 생명주기  (0) 2009.09.30
Spring 컨테이너와 아키텍처 구성  (0) 2009.09.30
Spring.NET 생명 주기  (0) 2009.09.30
posted by 방랑군 2009. 10. 6. 16:26
posted by 방랑군 2009. 10. 6. 15:30


 난 국어가 약하다. 언어로써 받아들이는 능력이 정말 형편없다는 걸 느낀다 ... --;

Spring framework 가장 중요한 것은 IoC 컨테이너다.

 먼 뜻일까? 먼가 거대한 숨어있는 기술이 있을거라고 생각하며
수많은 레퍼런스와 사이트를 뒤지며 간단히 설명하는 것을 찾기 위해
삽질하기 수일...
 허망 그 자체 --;

Spring 프레임워크는 AOP 기반 프레임워크라고 한다..
ㅋㅋ AOP...
개념은 "타겟 객체에 대한 호출을 중간에서 인터셉트할 수 있는 방법"이라는 것이다.

나에게 있어서 Spring 는 자유로움 빼았긴 프레임워크이다...

 아주 간단히 설명해서...
프레임워크에 필요한 설정과 바뀔수 있는 값들을 config 항목 즉, Spring  에서 정한
원칙적인 XML 틀에서 움직이는 프레임워크이다..
즉, Config 항목을 XML 의 항목을 다 알고 있어야 쓸수 있다느 것이다..

된장...... 이거 정말 안좋다...

1. 언제 그 항목을 다 마스터 하냐는 것이다....
   다 알아야 머가 필요없는지 뺄꺼 아닌가 ㅋㅋ
2. 기술 구현 프레임워크도 부담스러운데 거기다가 환경파일까지 ...
   부담이 2배다...
3. 사용자 CONFIG 를 하려면 .... 이건 확인 안해봤지만,
   된다면 지겨운 정해진 CONFIG 를 알려고 하기보단
   자기에 맞는 CONFIG 구성해서 기술구현에 끼워맞출려고 할 것이다.
4. 무엇보다 남 만든거 맞추는 거 정말 싫다...

역쉬 안좋다 --;

 이제 그만하련다 Spring ...
IoC 부분은 그만하고 각 필요한 부분의 기술만 좀 보고 말련다..

Spring 별로 매력없다..



   
posted by 방랑군 2009. 9. 30. 16:41


 주소  : http://kune.tistory.com/category/Spring.NET


그 많은 영어를 한글화 하시고 있는 분이다...
맨땅에 헤딩을 안해주시고 있어서 고맙긴 한데......

 핵심 기술만 알고 프로젝트에 적용하고 싶은 FRAMEWORK 은 아니다 .. 솔직히.....


-- 중요 포인트 --

1. Spring framework 의 가장 중요한 것은 IoC 컨테이너다.   
   - 이것만 다룰줄 알면 될 듯....

2. Spring.NET은 all or nothing 솔루션이 아니며모듈은 독립적으로 기능을 사용할 수 있다.
   - 필요한 것만... 물론, 핵심인 결정해야하는 단 한가지는비즈니스 로직을 Spring IoC 컨테이너를 이용하고 웹 레이어를 WebApplicationContext 와 멀티티어 서비스를 제공하느냐 이다.[Spring.Core 인 듯..]

3. 모듈

2.3. 모듈

Spring framework 는 잘구성된 모듈로서 많은 특징을 아래의 그림과 같이 가진다아래 그림은Spring.NET의 핵심 모듈을 보여준다.

Spring.Core 는 어플리케이션에서 DI를 사용하도록 설정하는 가장 기초적인 부분을 담당한다

Spring.Aop 는 Aspect-Oriented Programming ( 이하 AOP) 의 공통 기능을 수행한다. Spring  aspect 라이브러리는 transaction, logging, performance monitoring, caching, method retry, exception handling 에 사용하기 쉽게 정의되어 있다.

Spring.Data  data에 access하기 위해 더 효율적이고 일관된 기능을 제공한다

Spring.Data.NHibernate   ADO.NET  NHibernate 수행을 같은 transaction 에서 쉽게 제공하기위해Spring 의 선언적 transaction 관리 모듈이다. NHibernate 1.0 사용자는 data access 동작 수행을 API를 통해 쉽게 사용할 수 있다.

Spring.Web, Spring.Web.Extensions  ASP.NET web 어플리케이션 의 추상화 레벨로서databindingvalidation, page/control/module/provider 구성의 공통적인 방법을 효율적으로 제공한다.

Spring.Services  .NET remoting, Enterprise Service, ASMX web service같은 분산 기술에서 사용하는 .NET 개체를 처리하기 위한 모듈. 이런 서비스는 AOP 의 'decorated' 와 DI을 통해 구성할 수 있다

Spring.Testing.NUnit  NUnit 를 통해통합 테스트를 위한 모듈 제공

Spring.Core 모듈은 다음과같은 기능을 추가적으로 제공한다.

l  Expression Language - 런타임에 개체의 조작과 효율적인 쿼리 제공

l  Validation Framework - 비즈니스 개체의 복잡한 유효성 확인에 선언적이거나 프로그래밍적 방법을 제공하는 견고한 UI agnostic 프레임워크

l  Data binding GGramework - 데이터 바인딩을 수행하는 견고한 UI agnostic 프레임워크

l  Dynamic Reflection - 높은 성능의 reflection API 제공

l  Threading - Latch, Semaphore, Thread Local Storage 같은 additional 동시성의 추상화를 제공

l  Resource abstraction - file 로 부터의 InputStream 과 다형성과 프로토콜 독립적인 방법의 URL 을 처리하는 공통 인터페이스 제공

    
 


'GET > FrameWork' 카테고리의 다른 글

DI (Dependency Injection) 관련 프레임워크.  (0) 2009.10.06
방랑이가 생각하는 Spring.NET...  (0) 2009.10.06
객체의 생명주기  (0) 2009.09.30
Spring 컨테이너와 아키텍처 구성  (0) 2009.09.30
Spring.NET 생명 주기  (0) 2009.09.30
posted by 방랑군 2009. 9. 30. 15:32

참조 : http://resisa.tistory.com/52

이번 포스트에서는 클래스의 생성자와 소멸자를 통해서 객체의 생명주기에 대해서 알아보고 난 후에 Spring.NET에서 IoC컨테이너에서 객체의 생명주기에 알아보겠습니다.

먼저 변수는 값 타입과 참조 타입이 있으며 값 타입에는 int, double, char 등이며 참조 타입은 class 등입니다. 값 타입은 스택이라는 영역의 메모리에 저장됩니다. 반면에 참조 타입은 new라는 연산자를 통해서 객체가 생성되면 멤버변수들은 힙이라는 영역의 메모리에 저장되며 이 객체 변수는 힙 영역에 메모리를 가리키는 주소값을 가지며 스택에 저장이 됩니다. 그래서 참조 타입이라고 불립니다. 그리고 .NET에서는 가비지 수집기가 존재하여 C++에서 처럼 delete를 해주지 않아도 시점을 알 수는 없지만 가비지 수집기가 힙 영역에 사용하지 않는 메모리를 정리를 해줍니다. 그렇다면 .NET에서는 메모리에 대해서 개발자는 신경쓰지 않아도 될까요? 정답은 상황에 따라서 다릅니다. 우리가 선언하는 변수를 리소스라고 생각할 때 리소스에는 두 가지가 존재합니다. 바로 관리되는 리소스와 네이티브 리소스입니다. 관리되는 리소스는 사용자가 직접 만든 클래스나 .NET Framework에서 제공하는 클래스입니다. 네이티브 리소스는 파일핸들이나 API를 사용하는 리소스입니다. 이 네이티브 리소스는 힙 외부에 할당된 메모리를 사용하기 때문에 가비지 수집기에서 메모리를 해제할 수 없습니다. 네이티브 리소스를 사용하는 프로그램에서는 이 부분에 대한 메모리를 관리해주어야 메모리 누수가 발생하지 않게 됩니다. 그러면 이러한 리소스들을 정리해주는 IDisposable 패턴에 대해서 알아보고 객체의 수명주기에 대해서도 알아보도록 하겠습니다.

public class DisposableClass : IDisposable

{

    private SqlConnection connection;

    private IntPtr fileHandle;

 

    public DisposableClass()

    {

        System.Diagnostics.Debug.WriteLine("생성자입니다.");

    }

 

    ~DisposableClass()

    {

        Dispose(false);

        System.Diagnostics.Debug.WriteLine("소멸자입니다.");

    }

 

    [System.Runtime.InteropServices.DllImport("Kernel32")]

    private extern static Boolean CloseHandle(IntPtr handle);

 

    public void Dispose()

    {

        Dispose(true);

        GC.SuppressFinalize(this);

 

        System.Diagnostics.Debug.WriteLine("Dispose() 호출.");

    }

 

    protected virtual void Dispose(bool disposing)

    {

        if (disposing)

        {

            if (connection != null)

                connection.Dispose();

        }

 

        if (fileHandle != IntPtr.Zero)

        {

            CloseHandle(fileHandle);

            fileHandle = IntPtr.Zero;

        }

    }

 

}

=> DisposableClass 클래스는 관리되는 리소스인 SqlConnection과 네이티브 리소스인 IntPtr를 멤버변수로 가지고 있습니다. 또한 IDisposable 상속받아 구현하고 있는 것을 볼 수 있습니다. 여기서 IDisposable 패턴에 대해서는 자세히 설명하지 않겠지만 Dispose 메소드에서는 Dispose메소드가 호출이 되면 소멸자를 호출할 필요가 없다는 것을 가비지 수집기 에 알려주기 위한 부분(GC.SuppressFinalize(this))이 있으며 매개변수를 가지고 있는 Dispose 메소드가 있어 매개변수가 true일 때는 관리되는 리소스와 네이티브 리소스를 모두 정리하는 것을 알 수 있지만 false일 때(소멸자에서)는 네이티브 리소스만을 정리하는 것을 볼 수 있습니다. IDisposable 패턴에 대한 자세한 사항은 아래의 사이트를 참고 하세요.
http://msdn.microsoft.com/ko-kr/magazine/cc163392.aspx

그러면 이제 DisposableClass 클래스를 생성하도록 해보겠습니다.
 1번 : using 키워드 미사용
DisposableClass disposableClass = new DisposableClass();
 2번 : using 키워드 사용
using (DisposableClass disposableClass = new DisposableClass())

{

      

}

=> 2번처럼 using키워드를 사용하면 자동으로 Dispose메소드를 호출해주어 리소스를 해제시켜주는 것을 알 수 있습니다. 이렇게 using 키워드를 사용하기 위해서는 당연히 IDisposable
상속받아 구현해주어야 합니다.

여기서 저는 한가지 궁금증이 생겼습니다. SqlConnection과 같이 관리되는 리소스를 using키워드와 함께 객체로 생성하면 변수 connection의 값도 모두 해제되는 것인줄 알았습니다. 하지만 Dispose메소드는 변수 connection의 멤버변수들(리소스)을 해제해주는 것이지 connection의 값(참조주소)이 해제되는 것은 아닙니다. 물론 이 참조값은 int형의 4바이트뿐이 안됩니다. 또한 이 값은 가비지 수집기에 의해서 해제가 됩니다. 가비지 수집기는 어떻게 이 참조값을 해제해주는지 알 수 없지만 가비지 수집기에 명시적으로 이 값을 해제시키는 방법은 있습니다. 바로 connection변수에 null를 넣어주는 것입니다. GC.Collect()란 메소드는 명시적으로 가비지 수집기에게 메모리를 정리하라는 것을 알려줍니다. 만약에 connection변수에 null이란 값을 넣어주고 GC.Collect()를 호출하면 connection변수의 참조값을 바로 해제해줍니다. 실제적으로 코드가 생성되는 것을 한번 살펴보아야 확실히 알 수 있겠지만 제 생각으로는 uisng키워드에서 생성된 객체는 {}에서만 사용할 수 있으며 다른 곳에서는 사용할 수 없는 값이기 때문에 아마 {}안에서 마지막에 null를 대입해주는 것이 아닐까라는 생각이 듭니다.
posted by 방랑군 2009. 9. 30. 15:21

참조 : http://resisa.tistory.com/53

저번 포스트에 이어서 Spring 컨테이너 대해서 아키텍처와 함께 알아보도록 하겠습니다. 먼저 일반적으로 아키텍처를 구성은 프리젠테이션 레이어(PL) -> 비지니스 로직 레이어(BLL) -> 데이터 액세스 레이어(DAL)로 구성되고 모든 레이어에서는 테이블과 매핑되는 도메인 모델을 참조합니다. 이번 포스트에서는 비지니스 로직 레이어에 해당하는 클래스와 데이터 액세스 레이어에 해당하는 클래스를 만들고 두 레이어 간의 관계를 DI기능과 함께 살펴보도록 하겠습니다.

먼저 DAL에 클래스를 먼저 살펴보겠습니다.

public class DAL

{

    public DAL()

    {

        System.Diagnostics.Debug.WriteLine("데이터 생성자 호출");

    }

 

    ~DAL()

    {

        System.Diagnostics.Debug.WriteLine("데이터 소멸자 호출");

    }

 

    public void ExcuteDal1()

    {

        System.Diagnostics.Debug.WriteLine("데이터 Excute1() 호출");

    }

 

    public void ExcuteDal2()

    {

        System.Diagnostics.Debug.WriteLine("데이터 Excute2() 호출");

    }

 

    public void ExcuteDal3()

    {

        System.Diagnostics.Debug.WriteLine("데이터 Excute3() 호출");

    }

}

=> 생성되는 시점과 소멸되는 시점을 알기 위해서 출력창에 스트링을 찍어줍니다. 그리고 3개의 메소드를 가지고 있습니다. 실질적으로 여기서 DB와 커넥션을 하기 위한 패턴이나 프레임워크를 사용하여야 하는데 이번 포스트의 목적은 아키텍처 관점에서 두 레이어 사이의 관계와 레이어에서 생성되는 객체의 생명주기에 대해서 알아보기 위한 것이므로 생략하였습니다.

그럼 이제 BLL클래스를 만들어 보겠습니다. 2가지 방식으로 BLL 클래스를 만들어 보도록 하겠습니다.
1번째로 DAL클래스를 멤버변수로 가지고 있을 경우입니다.

public class BLL

{

    private DAL dal = new DAL();


    //private DAL dal;

 

    //public DAL Dal

    //{

    //  get { return dal; }

    //  set { dal = value; }

    //}


   
public BLL()

    {

        System.Diagnostics.Debug.WriteLine("비지니스 생성자 호출");

    }

 

    ~BLL()

    {

        System.Diagnostics.Debug.WriteLine("비지니스 소멸자 호출");

    }

 

    public void ExcuteBll1()

    {

        System.Diagnostics.Debug.WriteLine("비지니스 Excute1() 호출");

 

        dal.ExcuteDal1();

        dal.ExcuteDal2();

    }

 

    public void ExcuteBll2()

    {

        System.Diagnostics.Debug.WriteLine("비지니스 Excute2() 호출");

 

        dal.ExcuteDal2();

        dal.ExcuteDal3();

    }

}


2번째로는 BLL클래스의 메소드 안에 DAL클래스를 사용하는 경우입니다.

public class BLL

{

    public BLL()

    {

        System.Diagnostics.Debug.WriteLine("비지니스 생성자 호출");

    }

 

    ~BLL()

    {

        System.Diagnostics.Debug.WriteLine("비지니스 소멸자 호출");

    }

 

    public void ExcuteBll1()

    {

        System.Diagnostics.Debug.WriteLine("비지니스 Excute1() 호출");

       

        DAL dal = new DAL();

        dal.ExcuteDal1();

        dal.ExcuteDal2();

    }

 

    public void ExcuteBll2()

    {

        System.Diagnostics.Debug.WriteLine("비지니스 Excute2() 호출");

 

        DAL dal = new DAL();

        dal.ExcuteDal2();

        dal.ExcuteDal3();

    }

}

=> 1번과 2번에 차이는 무엇일까요? 1번에서는 BLL 객체를 만들면 DAL 클래스의 생성자가 호출이 되고 BLL 클래스의 생성자가 호출됩니다. 2번에서는 BLL 객체를 만들면 BLL 클래스의 생성자만 호출됩니다.
Spring에서 DI의 기능을 사용하기 위한 일반적인 방법은 생성자(Constructor Injection)나 프로퍼티(Setter Injection)를 이용해서 주입시키는 방법으로 바로 1번에 해당하는 구조입니다. 1번 구조로 DI기능을 이용해서 BLL 객체를 만들어보겠습니다. 1번 구조에서 new키워드를 사용한 부분을 제거하고 주석 부분을 해제한 후에 DI기능으로 DAL 객체를 생성해보겠습니다. 아래는 환경설정 파일과 컨테이너에서 BLL 객체를 가져오는 코드입니다.

<object id="dal" type="ObjectLifeCycle.DAL, ObjectLifeCycle" singleton="false"/>

 

<object id="bll" type="ObjectLifeCycle.BLL, ObjectLifeCycle" singleton="false">

  <property name="Dal" ref="dal" />

</object>

IApplicationContext ctx = ContextRegistry.GetContext();

BLL bll = ctx["bll"] as BLL;

 

bll.ExcuteBll1();

//bll.Dal = null;

//GC.Collect();

bll.ExcuteBll2();

=> 컨테이너에서 BLL 객체를 가져올 때와 1번 구조와의 차이점은 BLL과 DAL 객체의 생성시점입니다.
1번 구조에서는  위에서 말했듯이 DAL 생성자가 호출되고 BLL 생성자가 호출됩니다. 반면에 컨테이너에서 BLL 객체를 가져오면 BLL 생성자가 호출이 되고 DI기능에 의해서 DAL 생성자가 호출됩니다. 어느것이 먼저 생성되느냐에 차이점만 있습니다. 처음에 DI기능을 이용하면 프로퍼티를 호출하는 시점에 DAL 객체를 가져오는 줄 알았습니다. 하지만 BLL 객체를 생성한 이후에 바로 DI기능에 의해서 DAL 객체가 생성이 됩니다. 또한 이 구조에서는 DAL객체를 환경설정 파일에서 prototype으로 생성했지만 BLL 객체가 소멸되기 전까지 DAL 객체는 소멸이 되면 안됩니다. 왜냐하면 이전 포스트에서 가비지 수집기에 객체를 수집할 수 있는 방법으로 null을 대입해주는 방법이 있다고 하였고 위의 예에서 주석 부분을 제거하고 실행하면 예외가 발생하기 때문입니다. bll.ExcuteBll2()이 실행되기 직전에 가비지 수집기에 의해 DAL 객체가 소멸되었기 때문입니다.

그렇다면 바로 2번 구조처럼 BLL 클래스에 종속되지 않으면서 필요한 경우에 DAL 객체를 만들어서 사용하는 방법은 없을까요? 그 방법은 바로 메소드(Method Injection)로 주입해주는 방식입니다. 메소드로 주입해주는 방법은 두 가지 있으며 한 가지는 IObjectFactoryAware를 상속받는 방법과 Lookup Method Injection 방법입니다. IObjectFactoryAware 방법은 Spring 문서에서 권장을 하지 않기 때문에 두 번째 방식으로 구현해보겠습니다.
<object id="dal" type="ObjectLifeCycle.DAL, ObjectLifeCycle" singleton="false"/>

 

<object id="bll" type="ObjectLifeCycle.BLL, ObjectLifeCycle" singleton="false">

  <lookup-method name="Dal" object="dal" />

</object>


public abstract class BLL

{

    protected abstract DAL Dal();

 

    public BLL()

    {

        System.Diagnostics.Debug.WriteLine("비지니스 생성자 호출");

    }

 

    ~BLL()

    {

        System.Diagnostics.Debug.WriteLine("비지니스 소멸자 호출");

    }

 

    public void ExcuteBll1()

    {

        System.Diagnostics.Debug.WriteLine("비지니스 Excute1() 호출");

 

        DAL dal = Dal();

        dal.ExcuteDal1();

        dal.ExcuteDal2();

    }

 

    public void ExcuteBll2()

    {

        System.Diagnostics.Debug.WriteLine("비지니스 Excute2() 호출");

 

        DAL dal = Dal();

        dal.ExcuteDal2();

        dal.ExcuteDal3();

    }

}

=> 환경설정 파일에서는 lookup-method란 키워드와 object라는 프로퍼티(ref가 아닙니다)를 사용하고 있음을 볼 수 있고 BLL 클래스에서는 DAL 객체를 얻기 위한 추상 메소드 Dal()과 추상 메소드를 가지기 위해서 BLL 클래스가 추상 클래스로 변경되었습니다. 그리고 이전처럼 Spring 컨테이너에서 BLL 객체를 생성하고 BLL 객체의 메소드를 실행하면 DAL 객체가 메소드마다 각각 생성되는 것을 확인하실 수 있습니다. 이외에 예제 코드를 이용해서 BLL과 DAL클래스를 singleton과 prototype으로 번갈아 가면서 설정해서 실행해보면 실제로 객체들이 언제 만들어지고 언제 사라지는지를 알 수 있습니다. 또한 Spring에서 제공해주는 AdoTemplate를 singleton으로 생성할 때의 DB커넥션 문제라던지 lookup-method방식에의 추상클래스로 인한 TDD코드 작성시에 혹 나타날 문제점이라던지 추상클래스를 Base클래스로 사용하면서 아키텍처를 구성해보는 방법 등등 여러가지 테스트가 더 필요할 것 같습니다.

2번에 걸쳐 객체의 생명주기에 대해서 알아보았습니다. 객체에 생명주기에 관심이 없으신 분들은 객체 하나 만드는데 너무 복잡한거 아니냐 가비지 수집기가 있는데 왜 그런거에 관심을 가져야 하느냐 반문 하실 수 있습니다. 하지만 진짜 프로그래머라면 어떻게 하면 좀 더 효율적으로 프로그래밍을 할 것인가에 대한 고민은 밥을 먹는것과 같은거 아닐까요?

'GET > FrameWork' 카테고리의 다른 글

방랑이가 생각하는 Spring.NET...  (0) 2009.10.06
Spring.NET - 레퍼런스 문서 한글화 사이트..  (0) 2009.09.30
객체의 생명주기  (0) 2009.09.30
Spring.NET 생명 주기  (0) 2009.09.30
Hands-on Labs for EL 4.1 and Unity 1.2  (0) 2009.09.29
posted by 방랑군 2009. 9. 30. 15:19


 Spirng.NET의 IoC 컨테이너에서 객체의 생명주기에 대해서 알아보도록 하겠습니다. 먼저 IoC는 이제까지 new라는 연산자를 사용해서 객체를 생성해주던 것을 환경설정 파일에서 객체에 대한 설정을 해주고 프로그램에서 그 객체를 사용하는 것을 의미합니다. 환경설정 파일에서 객체를 생성해 줄 때 윈폼에서는 두 가지 방법이 있습니다. 바로 singleton과 prototype입니다. 아래는 두 가지 방식입니다. 디폴트로 singleton=true입니다.

<object id="car" type="ObjectLifeCycle.Car, ObjectLifeCycle" singleton="true"/>

 

<object id="car" type="ObjectLifeCycle.Car, ObjectLifeCycle" singleton="false"/> 


설정 파일에서 설정한 객체를 사용하기 위해서는 아래와 같이 사용합니다.
IApplicationContext ctx = ContextRegistry.GetContext();

 

Car car = ctx["car"] as Car;

Debug.WriteLine(car.GetHashCode().ToString());

=> IoC컨테이너를 불러와서 그 중에서 아이디가 "car"인 객체를 가져와서 그 객체의 고유한 값인 해쉬코드 값을 출력창에 보여줍니다. 이전에는 무조건 인터페이스 사용해야되는 줄 알았는데 그렇지 않는 것을 알 수 있었습니다. 그리고 여기서 singleton 방식은 해쉬코드값이 당연히 계속 같은 값을 찍을 것이고 prototype방식은 해쉬코드값이 계속 바뀔 것입니다.

다음 포스트에서는 여기에 DI기능을 추가하고 아키텍처에 Spring.NET를 사용할 경우에 객체의 생명주기를 어떤 방식으로 해야 더 효율적인가에 대해서 알아보도록 하겠습니다~
posted by 방랑군 2009. 9. 30. 15:17

1. prototype 패턴 (쌍둥이)
이미 생성된 객체를 복제해서 새로운 객체를 생성하는 방법

(게임블리오에서 clone() 개념으로 오브젝트의 정점 구성정보는 같지만 위치행렬와 같이 서로 다른 정보를 가져야하는것은 다르게 할수 있다)

- 객체 생성 방식이나 구성 형태, 표현 방식 등과 무관하게 객체를 생성 하고 싶을때 유용
- 생성할 객체가 run-time 시에 결정 되어 질때 유용


2. singleton 패턴 (단 한개!)
객체가 생성되는 개수를 제한 하는 형태의 설계가 singleton 패턴 이라 하고 극단적으로 제한되는 객체의 개수가 1개일 때를 감안한 패턴 (최대 N개 까지만 객체를 생성 하도록 제한)
- 패턴 구현시 모든 생성자는 protected 영역에 정의 되어야 함.
- 상속 관계에 놓인 클래스들에 대해 전체적으로 생성되는 객체의 최대 개수를 제한 하고자 할때 유용

'GET > Patten' 카테고리의 다른 글

singleton pattern 싱글톤 패턴  (0) 2009.09.30
posted by 방랑군 2009. 9. 30. 10:09
영어사전의 뜻
singleton
- 1 하나씩 일어나는 일, 홀로인 것, 독자(獨子) 2 (카드놀이의) 한 장 패(의 수)


뜻 : 
개체가 하나의 인스턴스를 가지는것을 보장하며, 그 개체를 전역적인 면에서 접근하는 것을 보장함.
생성된 인스턴스를 어디서든지 접근할 수 있게 하기 위한 패턴

KEY POINT :
 멀티스레딩 환경에서 여러개의 개체가 만들어 질 수 있다.
그래서, 동기화 한다.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;


namespace Console_Patten

{


    /// <summary>

    /// MySingleton을 실행하기 위한 클래스

    /// </summary>

    class Program

    {

        static void Main(string[] args)

        {

            MySingleton objTest1 = null;  //첫번째 인스턴스

            MySingleton objTest2 = null;  //두번째 인스턴스

            int i = 0;


            //첫번째 object에 MySingleton 인스턴스를 전달하고 시간을 출력해 본다.

            objTest1 = MySingleton.GetInstance();

            System.Console.WriteLine("인스턴스 호출 = " + System.DateTime.Now.ToLongTimeString()

                                        + ";" + "objTest1.TimeOfBirth() = " + objTest1.TimeOfBirth);

            //시간 지연을 위한 코드 *본인PC에서는 약 2초의 지연이 생김*

            for (i = 1; i < 1500000000; i++)

            {


            }


            //두번째 object에 MySingleton 인스턴스를 전달하고 시간을 출력해 본다.

            objTest2 = MySingleton.GetInstance();

            System.Console.WriteLine("인스턴스 호출 = " + System.DateTime.Now.ToLongTimeString()

                + ";" + "objTest2.TimeOfBirth() = " + objTest2.TimeOfBirth);

            

            //두개의 object의 생성시간이 같은것을 볼 수 있다.

            System.Console.ReadLine();

        }

    }


    /*

 static 멤버인 m_Instance는 객체의 단일 공유 인스턴스이다. 

 이 단일 공유 인스턴스는 공개함수인 GetInstance()에 의해 참조값이 반환된다.

 GetInstance는 m_Instace가 null인 경우에만 m_Instance를 생성하므로서 단일성을 유지한다

 생성자는 Private로 만들어 숨겨져 있다. 


 m_TimeOfBirth는 단지 테스트를 위한 멤버이다. 이것은 이 인스턴스가 생성된 시간을 가지고 있다. 

*/

    /// <summary>

    /// 유일성을 유지하고 싶은 클래스

    /// </summary>

    public class MySingleton

    {


        private static MySingleton m_Instanace = null;

        // 쓰레드로부터 안전한 인스턴스 생성을 위해 Mutex사용

        private static System.Threading.Mutex m_Mutex = new System.Threading.Mutex();

        #region 예제를 위한 부분 실사용중에는 별로 필요치 않음

        private static string m_TimeOfBirth = "";

        

        public string TimeOfBirth

        {

            get

            {

                return m_TimeOfBirth;

            }

        }

        #endregion

        /// <summary>

        /// 생성자 Private으로 존재한다. 필요하지 않은것은 아니며 단지 숨겨져 있을 뿐이다.

        /// </summary>

        private MySingleton()

        {

            System.Console.WriteLine("Singleton 생성시간 = " + System.DateTime.Now.ToLongTimeString());

            m_TimeOfBirth = System.DateTime.Now.ToLongTimeString();

        }

        /// <summary>

        /// 인스턴스를 리턴하는 함수이며 인스턴스가 null인 경우에만 인스턴스를 생성한다.

        /// </summary>

        /// <returns>MySingleton 인스턴스 (this.m_Instance)</returns>

        public static MySingleton GetInstance()

        {

            m_Mutex.WaitOne();

            if (m_Instanace == null)

            {

                m_Instanace = new MySingleton();

            }

            m_Mutex.ReleaseMutex();

            return m_Instanace;

        }

    }

}






야설:
singletone은 한번에 하나씩의 패만 보여준다는 의미를 가지고 있다. 좀더 일반적으로는 한번에 하나의 사건만 일어나도록 한다라는 의미로 해석할 수 있을 것 같다.

소프트웨어 엔지니어링 영역에서의 singletone은 객체지향프로그래밍시 클래스가 단하나의 사건, 즉 다시 말해서 단 하나의 인스턴스만을 가지도록 하는 패턴이다. 이 패턴은 주로 중요한자원을 관리하고자 할때, 다수의 인스턴스가 생성되지 않도록 만들어준다. 예컨데, 한번에 하나의 인스턴스만이 데이터베이스에 연결되는게 보장받기를 원하는 경우에 사용할 수 있을 것이다.
singletone은 다른 패턴들과도 어울려서 사용할 수 있는데, 다음과 같은 경우들이다.
  1. facade 객체는 단지 하나의 객체만이 요구되는데, 이를 보장하기 위해서 singletone을 사용할 수 있다. 예를들어 컴퓨터를 가동시키는 facade 클래스가 있다고 가정해보자. 컴퓨터를 가동시키기 위한 여러가지 공정들 즉 cpu freeze, memory load, cpu jump, cpu execute은 단지 하나의 객체가 생성되어서 수행되는 것을 보장해야 할 것이다.
  2. 때때로 singleton 패턴은 전역변수를 제한하기 위해서 사용되기도 한다. 전역변수를 모아서 하나의 single 클래스에 담아두는 방식으로 사용한다. 전역변수문제를 해결하기 위한 용도로 사용할 경우에 singleton 패턴자체가 전역클래스가 된다는 문제점이 있지만, namespace 충동물제를 해결하고 전역변수를 한 지점에서 관리할 수 있다는 것만으로도 singleton 패턴은 충분히 역할을 해낼 것이다.

'GET > Patten' 카테고리의 다른 글

prototype 패턴 (쌍둥이) 과 singleton 패턴  (0) 2009.09.30
posted by 방랑군 2009. 9. 29. 13:18


참조 : http://kingcrap.com/entry/Hands-on-Labs-for-EL-41-and-Unity-12



Enterprise Library 4.1 (EL) 과 Unity Application Block 1.2 (Unity) 에 대한 Hands-on Lab이 공개됐다. 국내 닷넷 개발 진영에도 범용 개발 프레임웍에 대한 관심이 고조되고 있고, 점차 많은 적용 사례가 공유되어 신규 개발에 힘을 실어주고 있는 시점에 EL과 Unity에 대한 HOL의 발표는 참으로 적절한 타이밍이라 여겨진다.

Enterprise Library는 이름이 의미하듯이 엔터프라이즈 애플리케이션 개발에 늘 고려하는, 즉 cross-cutting concern이라할 수 있는 기능을 모아 쉽게 적용할 수 있게 만든 라이브러리 모음집이다.

image

현재 EL 4.1에 포함되어 있는 Application block들로는 PIAB (Policy Injection Application Block), Logging, Caching, Cryptography, Data Access, Exception handling, Security, Validation 그리고 Unity가 있다. EL 4.1 HOL은 바로 이들 각각에 대한 HOL을 C#과 VB로 제공하여 쉽게 따라하며 익힐 수 있게 구성되어 있다.

image

좌측 그림 가운데 Interception (w/ PIAB and Unity), Unity, Validation은 새롭게 추가된 것들이며, 그외 나머지 HOL은 이전 버전의 것을 업데이트한 것이다.

EL과 Unity가 호스팅되고 있는 Codeplex를 방문하면 좀 더 상세한 정보를 알아 볼수 있다.
EL 4.1 ": http://www.codeplex.com/entlib
Unity : http://www.codeplex.com/unity

각각의 HOL의 다운로드 위치는 다음과 같다.
EL 4.1 HOL
Unity 1.2 HOL

MSDN에서도 EL과 Unity에 대한 상세한 정보를 찾을 수 있다.
EL 4.1
Unity 1.2

참고로 EL과 Unity를 포함하여 p&p에서 제공하는 각종 asset들을 활용하여 개발자 생산성이 40%까지 향상될 수 있다는 조사 보고서도 여기서 살펴볼 수 있다.

 

p&p 팀에서는 또한 Enterprise Library 다음 버전에 담고 싶은 기능에 대한 온라인 설문 조사를 진행하고 있다. 평소에 담고 싶었던 내용이 있었다면 한번쯤 의견을 전달하는 것도 좋을 것으로 생각된다.

EntLib_voting_2



'GET > FrameWork' 카테고리의 다른 글

방랑이가 생각하는 Spring.NET...  (0) 2009.10.06
Spring.NET - 레퍼런스 문서 한글화 사이트..  (0) 2009.09.30
객체의 생명주기  (0) 2009.09.30
Spring 컨테이너와 아키텍처 구성  (0) 2009.09.30
Spring.NET 생명 주기  (0) 2009.09.30
posted by 방랑군 2009. 9. 24. 17:25



using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;


using System.Reflection;


namespace Console_AOP

{

    class Program

    {

        static void Main(string[] args)

        {   


            /// string으로  객체 타입을 얻는다

            /// - typeName :System.Type.AssemblyQualifiedName

            ///

            Type atype = Type.GetType("Console_AOP.TEST, Console_AOP");

            // == Type atype = Type.GetType("Console_AOP.TEST");


            object a = System.Activator.CreateInstance(atype);


            /// 1. CASTING

            /// 

            TEST test = (TEST)a;

            string strAddress = test.GetAddress2(2);


            Console.WriteLine(strAddress);


            /// 2. INVOKE

            /// 

            // 메소드 : A.GetAddress()를 호출한다.

            MethodInfo mi = atype.GetMethod("GetAddress");

            strAddress = (string) mi.Invoke(a, null);


            Console.WriteLine(strAddress);


            MethodInfo mi2 = atype.GetMethod("GetAddress2");

            strAddress = (string)mi2.Invoke(a, new object[] {1234});


            Console.WriteLine(strAddress);


            // 프로퍼티 : A. HP의 값을 호출한다.

            PropertyInfo pi = atype.GetProperty("HP");

            strAddress = (string)pi.GetValue(a, null);


            Console.WriteLine(strAddress);

        }

    }



    class TEST

    {

        // 필드

        public string _Name;


        // 프로퍼티

        public string HP

        {

            get { return _HP; }

            set { _HP = value; }

        }

        private string _HP;


        // 메소드

        public TEST()

        {

            _Name = "황승재";

            _HP = "016-647-0678";

        }


        public string GetAddress()

        {

            return "서울시 염창동 동아3차아파트";

        }


        public string GetAddress2(int _NO)

        {

            return "서울시 양천구 목2동 537-20";

        }

    }

}






'GET > Reflection' 카테고리의 다른 글

string 으로 동적 참조 2 & System.Activator.CreateInstance  (0) 2009.09.24
posted by 방랑군 2009. 9. 24. 17:02



using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;


namespace Console_AOP

{

    class Program

    {

        static void Main(string[] args)

        {   


            /// string으로  객체 타입을 얻는다

            /// - typeName :System.Type.AssemblyQualifiedName

            ///

            Type atype = Type.GetType("Console_AOP.TEST, Console_AOP");

            // == Type atype = Type.GetType("Console_AOP.TEST");


            object a = System.Activator.CreateInstance(atype);


            TEST test = (TEST)a;


            Console.Write(test.GetAddress(10));

        }

    }



    class TEST

    {


        public string _Name;

        public string _HP;


        public string GetAddress(int _NO)

        {

            return "서울시 양천구 목2동 537-20";

        }

    }

}



결과 : 
서울시 양천구 목2동 537-20
posted by 방랑군 2009. 9. 24. 15:48


1. http://devray.tistory.com/category/.NET%20Framework/C%23%20Common

'GET > Attribute' 카테고리의 다른 글

간단 예제.  (0) 2009.09.24
* Conditional 어트리뷰트 사용  (0) 2009.09.24
* DllImport 어트리뷰트  (0) 2009.09.24
Attrubute(어트리뷰트)  (0) 2009.09.24
Attribute Oriented Programming  (0) 2009.09.24
posted by 방랑군 2009. 9. 24. 15:48
1. Obsolete 어트리뷰트
2.  사용자 어트리뷰트

====================================

Program.cs 코딩

------------------------------------

using System;

public class 특성
{
    public static void Main(string[] args)
    {
        Say1();
        Say2();
    }
   
    /// <summary>
    /// 닷넷 1.0 버전
    /// </summary>
    // Say1()은 오래된버전으로 가정하고 Say2()만 사용하고싶을때..ObsoleteAttribute사용 Attribute생략가능~
    [Obsolete("현재 메서드는 오래된 버전이므로, Say2()를 사용하세요." , false)] // false는 경고만 띄워주고,true는 컴파일오류내줌
    public static void Say1()
    {
        Console.WriteLine("안녕");
    }
   
    /// <summary>
    /// 닷넷 2.0 버전 이상
    /// </summary>
    public static void Say2()
    {
        Console.WriteLine("안녕하세열");
    }
}

=========================================

사용자정의특성.cs 코딩

-------------------------------------------

using System;

namespace 사용자정의특성
{
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple=true)]
    // AttributeUsate = 특정 멤버에만 특성적용해줌, AllowMultiple=true : 다중지정 가능하게..
   
    public class AuthorAttribute : Attribute
    {
        public string name;
        public AuthorAttribute(string name)
        {
            this.name = name;
        }
    }
   
    [AuthorAttribute("RedPlus")]
    class 사용자정의특성
    {
        static void Main(string[] args)
        {
            Say();
            ShowMetaData();
        }
        // 특성정보 읽어오기
        private static void ShowMetaData()
        {
            System.Attribute[] attrs = System.Attribute.GetCustomAttributes(typeof(사용자정의특성));
           
            foreach (var attr in attrs)
         {
         // if (attr is AuthorAttribute)
            // {
         //     AuthorAttribute aa = ( AuthorAttribute)attr;
               //     Console.WriteLine("{0}", aa.name);
            // }
                AuthorAttribute aa = attr as AuthorAttribute;
                if (aa != null)
                {
                    Console.WriteLine("{0}", aa.name);
                }
         }
        }
        static void Say() { Console.WriteLine("안녕하세요."); }
    }
}

==============================================



'GET > Attribute' 카테고리의 다른 글

참고 사이트.  (0) 2009.09.24
* Conditional 어트리뷰트 사용  (0) 2009.09.24
* DllImport 어트리뷰트  (0) 2009.09.24
Attrubute(어트리뷰트)  (0) 2009.09.24
Attribute Oriented Programming  (0) 2009.09.24
posted by 방랑군 2009. 9. 24. 15:36
* Conditional 어트리뷰트 사용
#define DEBUG       //DEBUG   
//어트리뷰트 사용  
// #undef DEBUG     //어튜리뷰트 사용 해제
using System;  
using System.Diagnostics;
namespace CSharpStudy  
{  
       class  MainClass  
       {  
           [Conditional("DEBUG")]  
           public static void DebugPrint()  
           {  
              Console.WriteLine("Debug");  
           }   

           [STAThread]  
           static void Main(string[] args)  
           {  
              DebugPrint();  
           }
       }
}

C#코드는 디버깅을 지원하기 위해서 Conditonal 어트리뷰트를 사용 하며 지원을 합니다. Conditional 어트리뷰트는 사용자가 정의한 값에 의존해서 해당 메소드를 실행 시키도록 합니다. Conditional 어트리뷰트는 System.Diagnositcs 네임스페이스 안에 정의 되어 있습니다.

즉, #define을 설정해주지 않으면 실행 되지 않으며 설정시 실행이 됩니다.
Conditional 어트리뷰트는 클래스나 구조체 안에 있는 메소드에만 접착시킬 수 있다. 또한 그 메소드는 반드시 void형이어야 하며, 여러 Conditional어트리뷰트를 접착시키면 그중 하나만 위치지정 파라미터가 정의 되어 있어도 해당 메소드는 실행됩니다.

'GET > Attribute' 카테고리의 다른 글

참고 사이트.  (0) 2009.09.24
간단 예제.  (0) 2009.09.24
* DllImport 어트리뷰트  (0) 2009.09.24
Attrubute(어트리뷰트)  (0) 2009.09.24
Attribute Oriented Programming  (0) 2009.09.24
posted by 방랑군 2009. 9. 24. 15:35
* DllImport 어트리뷰트
   DllImport 어트리뷰트는 C#안에서 Unmanaged 코드를 사용 할 수 있게 합니다. Unmanaged 코드란 닷넷 환경밖에서 개발된 코드를 말하며 예를들면 DLL 파일들안에 컴파일된 표준 , DllImport 어트리뷰트는 System.Runtime.InteropServices 네임스페이스안에서 정의 되어있습니다.

using System  
using System.Runtime.InteopServices;  
class testClass  
{  
        [DllImport("User32.dll"]  
        public static extern int MessageBox(int h, string m, string c, int type);   

        static void Main()   
        {  
             MessageBox(0, "Hello world!", "C#", 0);  
        }  
}

다음은 Win32 API중 User32.dll안에 있는 MessageBox함수를 호출형태 입니다.
int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);  

     [DllImport("kernel32.dll")]  
     private static extern bool Beep(int freq, int dur);   

     [STAThread]  
     static void Main(string[] args)  
     {  
          MessageBox(0, "MessageBox Text", "DllImport Test", 2);  
          Beep(2600,1000);  
     }

위코드는 외부의 비관리(Unmanaged)코드에 있는 DLL을 특정 프로세스 메모리에 로딩하여 해당 메소드를 호출하여 사용한 예입니다.

※ extern 키워드 : 어떤 메서드가 현재 프로그램 외부에 있음을 나타내는 키워드

'GET > Attribute' 카테고리의 다른 글

참고 사이트.  (0) 2009.09.24
간단 예제.  (0) 2009.09.24
* Conditional 어트리뷰트 사용  (0) 2009.09.24
Attrubute(어트리뷰트)  (0) 2009.09.24
Attribute Oriented Programming  (0) 2009.09.24
posted by 방랑군 2009. 9. 24. 14:52

 특성. - 코드에 대한 설명문매타데이타)

1. 멤버 앞에 [특성(특성값)] 식으로 붙여서 사용
2. 분야(Web, XML..) 에 따라서 많은 내장 특성이 있다.
3. 사용자 정의 특성을 만들고자 할 때에는 System.Attribute 를 상속 받아 설계
4. 특성을 통해서 런타임 시에 추가적인 기능을 부여가능.
5. 자동차로 따지면 자동차 악세사리



01 | 개요(Overview of Attributes)
    어트리뷰트는 클래스 안에 메타정보를 포함 시킬 수 있는 새로운 기술입니다. 어트리뷰트는 선언적 컴파일을 지원하기 때문에 코딩에 많은 이점을 주고 있으며 특히 컴포넌트를 만들 때 유용하게 쓸 수 있습니다.

실제, 어트리뷰트는 클래스 멤버변수로 관리하기에는 적절하지 않고 주로 코드 외부에서 어떤 자료형에 대한 서술이 필요할 때 많이 사용하는 편입니다.

Attributes 소개
    어트리뷰트는 최근 자바 이노테이션(Annotation)의 등장으로 어트리뷰트 오리엔티드 프로그래밍(attribute oriented programming)에 대한 관심이 많아 지고 있습니다. 하지만 어트리뷰트 오리엔티드 프로그래밍은 마이크로소프트(이하 MS)진영에서 COM, COM+개발에서 부분적으로 이미 사용하고 있고 닷넷 프레임워크 경우 어트리뷰티드 프로그래밍이라는 이름으로 지원하고 있습니다.

어트리뷰트 오렌티드 프로그래밍이란 프로그램 레벨에서의 마킹 기법입니다.
이를 사용하면 프로그램을 개발할 때 프로그램과 관련된 메타데이터를 정보를 저장하고 이 정보를 이용하여 디자인&컴파일 타임 로딩 또는 런타임 시에 원하는 동작을 수행 하도록 할 수 있습니다.


예를 들면 트랜잭션(Transaction)이라는 어트리뷰트를 선언한 클래스는 클래스의 메소드를 실행할 때 트랜잭션 컨텍스트 내에서 수행 되도록 한다. 이러한 기법은 코어 비즈니스 로직과 트랜잭션과 로깅과 같은 횡단 관심사(Cross-cutting concerns)를 분리한다는 점에서 AOP(Aspect Oriented Programming) 기법과 유사합니다.

* 어트리뷰티드 프로그래밍 패러다임의 시작
    어트리뷰티드 프로그래밍 기법은 COM 기반 프로그래밍에서의 인터페이스 정의 언어(Interface Definition Language)에서 사용되기 시작했다. 라이브러리와 클래스의 uuid나 helpstring같은 프로그램에 대한 메타데이터 값들을 라이브러리나 클래스의 정의에 다음과 같이 선언해 컴파일 시에 참조할 수 있도록 지원 합니다.

[uuid(74731E6F-A0E8-47FB-833C-8D6C75E85981),
helpstring("MessengerAx Control"), control]
coclass MessengerAx


이러한 기법은 COM+ 기반을 발전하면서 애플리케이션의 트랙젹선 설정과 풀리, 보안 설정 등의 메타데이터 정보를 구성요소 서비스와 같은 별도의 저장소를 이용해 등록한 후 이정보를 런타임시 참조를 해야 동작이 가능합니다.

하지만 이러한 기능을 닷넷 에서는 이보다 한 단계 더 발전된 형태로 어트리뷰트를 별도의 저장소가 아닌 프로그램 내에 직접 저장할 수 있고 동작이 가능합니다.

어트리뷰트는 클래스 뿐만 아니라 데이터 구조, 열거자 그리고 어셈블리와 같은 프로그래밍적 요소들의 실행시 행동에 대한 정보를 기술 할수 있습니다. 어트리뷰트를 아티클을 보시는 여러분들은 코드에 대해서 어떻게 지정되고 사용되는지에 대한 주석으로 생각 할수도 있습니다. 하지만 일반 주석의 의해 전달되는 정보들은 일정한 틀이 없고 그것을 정형화하기 힘듭니다. 또한 그 정보들에 대해 런타임상의 접근하기가 어렵습니다.

어트리뷰트는 메타데이터지만 일종의 클래스입니다.
어트리뷰트를 정의해서 사용하게 되면 어떠한 클래스에 대해 설명할 때 이 어트리뷰트를 사용해서 설명할수 있고 주석처럼 직접 소스를 보아야 알수 있는 정보들을 어셈블리 안에 직접 넣거나 그 정보을 보는 방법도 코드레벨에서 가능합니다. 즉, 어트리뷰트는 작성한 클래스와 어떤 정보들(ex>이 클래스는 누가 디자인했고 라이센스는 누구한테 있으며 버전은 몇버전이다) 을 연결시켜주는 기술을 지원합니다.

* 어트리뷰트 시용
어트리뷰트를 사용할 수 있는 요소는 다음과 같습니다.
어트리뷰트를 사용할 수 있는 요소들
 어셈블리, 모듈, 클래스, 구조체, 열거형, 변수, 생성자, 메소드, 프로퍼티, 필드, 이벤트, 인터페이스, 파라미터,
 반환값, 델리게이트

* 어트리뷰트 문장 형식
attribute(positional_parameters, name_parameter = value, ...)]

'[ ]' 안에 무슨 메소드와 같은 것이 쓰여져 있습니다. 그리고 그 메소드 안에 파라미터들이 있습니다.

여기서 파리미터는 두가지를 의미합니다. 하나는 위치지정 파라미터(positional_parameter)로 꼭 필요한 정보들을 기술할때 쓰며 위치 지정 파라미터는 반드시 넣어줘야하는 정보들입니다. 두번째로는 명명 파라미터(name_parameter)는 꼭 필요하지 않지만 사용자에 따라서 넣을 수도 있고 그렇지 않을수도 있습니다. 어트리뷰트 안에 추가적인 정보를 집어 넣을때 사용됩니다.

* 어트리뷰트 사용 예
[AdditionalInfo("2009-05-20")]
public class Test
{
   //TODO :  내용
}

여기서 AdditionalInfo는 어트리뷰트 이며 "2009-05-20"는 위치지정 파리미터가 됩니다. 개발하고자하는 코드바로위에 어트리뷰트를 써주면 됩니다.


'GET > Attribute' 카테고리의 다른 글

참고 사이트.  (0) 2009.09.24
간단 예제.  (0) 2009.09.24
* Conditional 어트리뷰트 사용  (0) 2009.09.24
* DllImport 어트리뷰트  (0) 2009.09.24
Attribute Oriented Programming  (0) 2009.09.24
posted by 방랑군 2009. 9. 24. 14:49

'GET > Attribute' 카테고리의 다른 글

참고 사이트.  (0) 2009.09.24
간단 예제.  (0) 2009.09.24
* Conditional 어트리뷰트 사용  (0) 2009.09.24
* DllImport 어트리뷰트  (0) 2009.09.24
Attrubute(어트리뷰트)  (0) 2009.09.24
posted by 방랑군 2009. 9. 24. 13:47


App.config

<?xml version="1.0" encoding="utf-8" ?>

<configuration>


  <configSections>

    <section name="unity" type="Console_Config_User.UserInfo,Console_Config_User" />

  </configSections>


  <unity>

    <NAME>황승재</NAME>

    <ADDRESS>염창동</ADDRESS>

    <HP>016-647-0678</HP>

  </unity>

</configuration>


unity.xml - 객체만들 부분만 뽑아서 XML 만든다.

<?xml version="1.0" encoding="utf-8" ?>

<unity>

  <NAME>황승재</NAME>

  <ADDRESS AD1="서울시" AD2="염창동" AD3="동아3차아파트" AD4="307동 1101호" />

  <HP>016-647-0678</HP>

</unity> 



XSD.EXE 로 XSD 파일 만들고 CLASS 객체 파일 만든다.

>xsd.exe unity.xml


>xsd.exe unity.xsd /c


unity.cs

//------------------------------------------------------------------------------

// <auto-generated>

//     This code was generated by a tool.

//     Runtime Version:2.0.50727.3082

//

//     Changes to this file may cause incorrect behavior and will be lost if

//     the code is regenerated.

// </auto-generated>

//------------------------------------------------------------------------------


using System.Xml.Serialization;


// 

// This source code was auto-generated by xsd, Version=2.0.50727.1432.

// 

namespace Console_Config_User

{


    /// <remarks/>

    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.1432")]

    [System.SerializableAttribute()]

    [System.Diagnostics.DebuggerStepThroughAttribute()]

    [System.ComponentModel.DesignerCategoryAttribute("code")]

    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]

    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]

    public partial class unity

    {


        private string nAMEField;


        private string hpField;


        private unityADDRESS[] aDDRESSField;


        /// <remarks/>

        [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]

        public string NAME

        {

            get

            {

                return this.nAMEField;

            }

            set

            {

                this.nAMEField = value;

            }

        }


        /// <remarks/>

        [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]

        public string HP

        {

            get

            {

                return this.hpField;

            }

            set

            {

                this.hpField = value;

            }

        }


        /// <remarks/>

        [System.Xml.Serialization.XmlElementAttribute("ADDRESS", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]

        public unityADDRESS[] ADDRESS

        {

            get

            {

                return this.aDDRESSField;

            }

            set

            {

                this.aDDRESSField = value;

            }

        }

    }


    /// <remarks/>

    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.1432")]

    [System.SerializableAttribute()]

    [System.Diagnostics.DebuggerStepThroughAttribute()]

    [System.ComponentModel.DesignerCategoryAttribute("code")]

    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]

    public partial class unityADDRESS

    {


        private string aD1Field;


        private string aD2Field;


        private string aD3Field;


        private string aD4Field;


        /// <remarks/>

        [System.Xml.Serialization.XmlAttributeAttribute()]

        public string AD1

        {

            get

            {

                return this.aD1Field;

            }

            set

            {

                this.aD1Field = value;

            }

        }


        /// <remarks/>

        [System.Xml.Serialization.XmlAttributeAttribute()]

        public string AD2

        {

            get

            {

                return this.aD2Field;

            }

            set

            {

                this.aD2Field = value;

            }

        }


        /// <remarks/>

        [System.Xml.Serialization.XmlAttributeAttribute()]

        public string AD3

        {

            get

            {

                return this.aD3Field;

            }

            set

            {

                this.aD3Field = value;

            }

        }


        /// <remarks/>

        [System.Xml.Serialization.XmlAttributeAttribute()]

        public string AD4

        {

            get

            {

                return this.aD4Field;

            }

            set

            {

                this.aD4Field = value;

            }

        }

    }


    /// <remarks/>

    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.1432")]

    [System.SerializableAttribute()]

    [System.Diagnostics.DebuggerStepThroughAttribute()]

    [System.ComponentModel.DesignerCategoryAttribute("code")]

    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]

    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]

    public partial class NewDataSet

    {


        private unity[] itemsField;


        /// <remarks/>

        [System.Xml.Serialization.XmlElementAttribute("unity")]

        public unity[] Items

        {

            get

            {

                return this.itemsField;

            }

            set

            {

                this.itemsField = value;

            }

        }

    }

}



UserInfo.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;


using System.Configuration;

using System.Xml;


namespace Console_Config_User

{

    class UserInfo : System.Configuration.IConfigurationSectionHandler

    {


#region IConfigurationSectionHandler 멤버


public object Create(object parent, object configContext, System.Xml.XmlNode section)

{

    //throw new NotImplementedException();

    XmlDocument doc = new XmlDocument();

    doc.LoadXml(section.OuterXml);

    Console_Config_User.unity objClass = new unity();

    objClass = (unity)xxml.ToInstance(doc, typeof(unity));


    return objClass;

}


#endregion

    }

}



Program.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;


using System.Configuration;


namespace Console_Config_User

{

    class Program

    {

        static void Main(string[] args)

        {


            //object config = ConfigurationManager.GetSection("unity");


            unity container = new unity();

            container = (unity)ConfigurationManager.GetSection("unity");

            

        }

    }

}




결과.





posted by 방랑군 2009. 9. 24. 13:05


개념은 "타겟 객체에 대한 호출을 중간에서 인터셉트할 수 있는 방법"이라는 것이다. 개발 프레임워크 입장에서 생각해본다면 얼마나 근사한 구조인가. 타겟 객체( 개발자가 개발)에 대한 모든 호출( 개발자가 만든 코드에서의 호출)을 개발 프레임워크에서 캐취할 수 있다는 것은 많은 장점을 가지고 있다.
posted by 방랑군 2009. 9. 24. 11:27

첨부파일 :

XMLFile2.xml

<?xml version="1.0" encoding="UTF-8" ?>

<Root>

  <Record>

    <Field1>Field1_0</Field1>

    <Field2>Field2_0</Field2>

  </Record>

  <Record2 Field2="Field2_0" Field3="Field3_1" />

  <Field1>Field1_0</Field1>

  <Field2>Field2_0</Field2>

</Root>




>xsd.exe XMLFile2.xml
XMLFile2.xml

<?xml version="1.0" encoding="utf-8"?>

<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">

  <xs:element name="Root">

    <xs:complexType>

      <xs:sequence>

        <xs:element name="Field1" type="xs:string" minOccurs="0" />

        <xs:element name="Field2" type="xs:string" minOccurs="0" />

        <xs:element name="Record" minOccurs="0" maxOccurs="unbounded">

          <xs:complexType>

            <xs:sequence>

              <xs:element name="Field1" type="xs:string" minOccurs="0" />

              <xs:element name="Field2" type="xs:string" minOccurs="0" />

            </xs:sequence>

          </xs:complexType>

        </xs:element>

        <xs:element name="Record2" minOccurs="0" maxOccurs="unbounded">

          <xs:complexType>

            <xs:attribute name="Field2" type="xs:string" />

            <xs:attribute name="Field3" type="xs:string" />

          </xs:complexType>

        </xs:element>

      </xs:sequence>

    </xs:complexType>

  </xs:element>

  <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">

    <xs:complexType>

      <xs:choice minOccurs="0" maxOccurs="unbounded">

        <xs:element ref="Root" />

      </xs:choice>

    </xs:complexType>

  </xs:element>

</xs:schema>


>xsd.exe XMLFile2.xsd /c
XMLFile2.cs

//------------------------------------------------------------------------------

// <auto-generated>

//     This code was generated by a tool.

//     Runtime Version:2.0.50727.3082

//

//     Changes to this file may cause incorrect behavior and will be lost if

//     the code is regenerated.

// </auto-generated>

//------------------------------------------------------------------------------


using System.Xml.Serialization;


// 

// This source code was auto-generated by xsd, Version=2.0.50727.1432.

// 



/// <remarks/>

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.1432")]

[System.SerializableAttribute()]

[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.ComponentModel.DesignerCategoryAttribute("code")]

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]

[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]

public partial class Root {

    

    private string field1Field;

    

    private string field2Field;

    

    private RootRecord[] recordField;

    

    private RootRecord2[] record2Field;

    

    /// <remarks/>

    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]

    public string Field1 {

        get {

            return this.field1Field;

        }

        set {

            this.field1Field = value;

        }

    }

    

    /// <remarks/>

    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]

    public string Field2 {

        get {

            return this.field2Field;

        }

        set {

            this.field2Field = value;

        }

    }

    

    /// <remarks/>

    [System.Xml.Serialization.XmlElementAttribute("Record", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]

    public RootRecord[] Record {

        get {

            return this.recordField;

        }

        set {

            this.recordField = value;

        }

    }

    

    /// <remarks/>

    [System.Xml.Serialization.XmlElementAttribute("Record2", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]

    public RootRecord2[] Record2 {

        get {

            return this.record2Field;

        }

        set {

            this.record2Field = value;

        }

    }

}


/// <remarks/>

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.1432")]

[System.SerializableAttribute()]

[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.ComponentModel.DesignerCategoryAttribute("code")]

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]

public partial class RootRecord {

    

    private string field1Field;

    

    private string field2Field;

    

    /// <remarks/>

    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]

    public string Field1 {

        get {

            return this.field1Field;

        }

        set {

            this.field1Field = value;

        }

    }

    

    /// <remarks/>

    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]

    public string Field2 {

        get {

            return this.field2Field;

        }

        set {

            this.field2Field = value;

        }

    }

}


/// <remarks/>

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.1432")]

[System.SerializableAttribute()]

[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.ComponentModel.DesignerCategoryAttribute("code")]

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]

public partial class RootRecord2 {

    

    private string field2Field;

    

    private string field3Field;

    

    /// <remarks/>

    [System.Xml.Serialization.XmlAttributeAttribute()]

    public string Field2 {

        get {

            return this.field2Field;

        }

        set {

            this.field2Field = value;

        }

    }

    

    /// <remarks/>

    [System.Xml.Serialization.XmlAttributeAttribute()]

    public string Field3 {

        get {

            return this.field3Field;

        }

        set {

            this.field3Field = value;

        }

    }

}


/// <remarks/>

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.1432")]

[System.SerializableAttribute()]

[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.ComponentModel.DesignerCategoryAttribute("code")]

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]

[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]

public partial class NewDataSet {

    

    private Root[] itemsField;

    

    /// <remarks/>

    [System.Xml.Serialization.XmlElementAttribute("Root")]

    public Root[] Items {

        get {

            return this.itemsField;

        }

        set {

            this.itemsField = value;

        }

    }

}




쓸데없는 Attribute 제거 후 객체 모양

using System.IO;

using System.Xml;

using System.Xml.Serialization;


using System.Collections.Generic;

using System.Linq;

using System.Text;



namespace Console_XML.In4

{


    /// <remarks/>

    [System.Serializable]

    //[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]

    public class Root

    { 


        /// <remarks/>

        

        public RootRecord Record

        {

            get { return _Record; }

            set { _Record = value; }

        }

        private RootRecord _Record = new RootRecord();



        /// <remarks/>

        

        public RootRecord2 Record2

        {

            get { return _Record2; }

            set { _Record2 = value; }

        }

        private RootRecord2 _Record2 = new RootRecord2();



        /// <remarks/>

        

        public string Field1

        {

            get { return _Field1; }

            set { _Field1 = value; }

        }

        private string _Field1 = "";



        /// <remarks/>

        

        public string Field2

        {

            get { return _Field2; }

            set { _Field2 = value; }

        }

        private string _Field2 = "";


    }


    /// <remarks/>

    [System.Serializable]    

    public class RootRecord

    {


        /// <remarks/>

        

        public string Field1

        {

            get { return _Field1; }

            set { _Field1 = value; }

        }

        private string _Field1 = "";



        /// <remarks/>

        

        public string Field2

        {

            get { return _Field2; }

            set { _Field2 = value; }

        }

        private string _Field2 = "";


    }


    /// <remarks/>

    [System.Serializable]    

    public class RootRecord2

    {


        /// <remarks/>

        [System.Xml.Serialization.XmlAttributeAttribute()]

        public string Field2

        {

            get { return _Field2; }

            set { _Field2 = value; }

        }

        private string _Field2 = "";



        /// <remarks/>

        [System.Xml.Serialization.XmlAttributeAttribute()]

        public string Field3

        {

            get { return _Field3; }

            set { _Field3 = value; }

        }

        private string _Field3 = "";


    }


}



XML <-> CLASS 할 함수

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;



using System.Xml;

using System.IO;

using System.Xml.Serialization;



namespace Console_XML

{

    class xxml

    {


        /// <summary>

        /// XML -> yyyyMMdd\FILE

        /// </summary>

        /// <param name="doc"></param>

        /// <param name="path"></param>

        public static void XMLDoctoFile(XmlDocument doc, string path)

        {

            string _Date = DateTime.Now.ToString("yyyyMMdd", System.Globalization.DateTimeFormatInfo.InvariantInfo);

            string[] _path = path.Split(new char[] { '\\' });

            string _fullpath = "";

            for (int i = 0; i < _path.Length - 1; i++)

            {

                _fullpath += _path[i] + "\\";


            }

            // 디렉토리 검색

            if (!System.IO.Directory.Exists(_fullpath + "\\" + _Date))

            {

                Directory.CreateDirectory(_fullpath + "\\" + _Date);

            }


            path = _fullpath + "\\" + _Date + "\\" + _path[_path.Length - 1];


            XmlTextWriter writer = new XmlTextWriter(path, new UTF8Encoding());

            try

            {

                writer.Formatting = Formatting.Indented;

                writer.Indentation = 4;

                doc.WriteContentTo(writer);

            }

            finally

            {

                writer.Close();

            }

        }



        /// <summary>

        /// XML -> yyyyMMdd\FILE

        /// </summary>

        /// <param name="doc"></param>

        /// <param name="path"></param>

        public static void XMLDoctoFileEx(XmlDocument doc, string path)

        {

            string _Date = DateTime.Now.ToString("yyyyMMdd", System.Globalization.DateTimeFormatInfo.InvariantInfo);

            string _Hour = DateTime.Now.ToString("HH", System.Globalization.DateTimeFormatInfo.InvariantInfo);

            string[] _path = path.Split(new char[] { '\\' });

            string _dirPath = "";

            string _fullpath = "";

            for (int i = 0; i < _path.Length - 1; i++)

            {

                _fullpath += _path[i] + "\\";


            }


            _dirPath = _fullpath + "\\" + _Date + "\\" + _Hour;

            // 디렉토리 검색

            if (!System.IO.Directory.Exists(_dirPath))

            {

                Directory.CreateDirectory(_dirPath);

            }


            path = _dirPath + "\\" + _path[_path.Length - 1];


            XmlTextWriter writer = new XmlTextWriter(path, new UTF8Encoding());

            try

            {

                writer.Formatting = Formatting.Indented;

                writer.Indentation = 4;

                doc.WriteContentTo(writer);

            }

            catch (Exception err)

            {

                System.Diagnostics.EventLog.WriteEntry("VTFramework", "[vS_XML:XMLDoctoFileEx]:" + err.Message, System.Diagnostics.EventLogEntryType.Error);

            }

            finally

            {

                writer.Close();

            }

        }


        /// <summary>

        /// 객체를 xmlDocument로 전환 하는 함수.

        /// </summary>

        /// <param name="obj"></param>

        /// <returns></returns>

        public static XmlDocument ToMessage(object obj)

        {

            try

            {

                XmlSerializer serializer = new XmlSerializer(obj.GetType());

                MemoryStream stream = new MemoryStream();

                StreamReader reader = new StreamReader(stream);

                serializer.Serialize(stream, obj);

                stream.Position = 0;

                XmlDocument doc = new XmlDocument();

                doc.LoadXml(reader.ReadToEnd());

                try

                {

                    return doc;

                }

                finally

                {

                    reader.Close();

                    stream.Close();

                }

            }

            catch (Exception exc)

            {

                System.Diagnostics.EventLog.WriteEntry("VTFramework", "[vS_XML:ToMessage]:" + exc.Message, System.Diagnostics.EventLogEntryType.Error);

                throw new Exception("객체 생성중 오류가 발생했읍니다![ToInstance", exc);

            }

        }


        /// <summary>

        /// xmlDocument를 객체로 변환하는 함수

        ///  XML -> CLASS

        /// ex)

        ///   1. 변환할 클래스의 필드가 적어도 많아도 적용이 됨

        ///   2. 다른 필드가 존재해도 적용이 됨

        /// </summary>

        /// <param name="doc"></param>

        /// <param name="type"></param>

        /// <returns></returns>

        public static object ToInstance(XmlDocument doc, System.Type type)

        {

            try

            {

                XmlSerializer serializer = new XmlSerializer(type);

                MemoryStream writeStream = new MemoryStream();

                MemoryStream readStream = new MemoryStream();


                XmlTextWriter writer = new XmlTextWriter(writeStream, null);

                doc.WriteContentTo(writer);

                writer.Flush();


                writeStream.Position = 0;


                writeStream.WriteTo(readStream);

                writer.Close();

                writeStream.Close();


                readStream.Position = 0;

                XmlTextReader reader = new XmlTextReader(readStream);

                try

                {

                    return serializer.Deserialize(reader);

                }

                finally

                {

                    reader.Close();

                    readStream.Close();

                }

            }

            catch (Exception exc)

            {

                throw new Exception("객체 생성중 오류가 발생했읍니다![ToInstance", exc);

            }

        }

    }

}




XML -> CLASS 객체로 변환 소스

doc.Load(@"XMLFile2.xml");


Console_XML.In4.Root objInstance3 = (Console_XML.In4.Root)xxml.ToInstance(doc, typeof(Console_XML.In4.Root));


posted by 방랑군 2009. 9. 23. 15:23

        static void Main(string[] args)

        {



            StringBuilder strXML = new StringBuilder(); 

            strXML.AppendLine(@"<?xml version=""1.0"" encoding=""utf-8"" ?>");

            strXML.AppendLine(@"<unity>");

            strXML.AppendLine(@"<NAME>황승재</NAME>");

            strXML.AppendLine(@"<ADDRESS AD1=""서울시"" AD2=""염창동"" AD3=""동아3차아파트"" AD4=""307동 1101호"" />");

            strXML.AppendLine(@"<HP>016-647-0678</HP>");

            strXML.AppendLine(@"</unity>");

            strXML.AppendLine("");



            XmlDocument doc = new XmlDocument();

            doc.LoadXml(strXML.ToString());


            ///

            ///

            string strNode1 = doc.SelectSingleNode("unity/NAME").InnerText;

            string strNode2 = doc.SelectSingleNode("unity/ADDRESS").Attributes["AD1"].Value;



            doc = null;

        }




posted by 방랑군 2009. 9. 23. 14:48


  <unity>

    <NAME>황승재</NAME>

    <ADDRESS AD1="서울시" AD2="염창동" AD3="동아3차아파트" AD4="307동 1101호" />

    <HP>016-647-0678</HP>

  </unity>


ADDRESS 의 Attribute 값 가져오는 법


section.SelectSingleNode("ADDRESS").Attributes["AD1"].Value

"서울시"


/// 더미..

section.SelectSingleNode("ADDRESS").OuterXml

"<ADDRESS AD1=\"서울시\" AD2=\"염창동\" AD3=\"동아3차아파트\" AD4=\"307동 1101호\" />"

section.SelectSingleNode("ADDRESS").Attributes["AD1"].OuterXml

"AD1=\"서울시\""




ADDRESS 의 Element 값 가져오는 법

section.SelectSingleNode("NAME").InnerText; 

"황승재"



IConfigurationSectionHandler  에서 값 할당

#region IConfigurationSectionHandler 멤버


public object Create(object parent, object configContext, System.Xml.XmlNode section)

{

    //throw new NotImplementedException();


    UserInfo obj = new UserInfo();


    

    obj._NAME    = section.SelectSingleNode("NAME").InnerText; // section 이용하여 config 값 넣는다.  

    obj._ADDRESS = doc.SelectSingleNode("unity/ADDRESS").Attributes["AD1"].Value;

    obj._HP      = section.SelectSingleNode("HP").InnerText; // section 이용하여 config 값 넣는다.

    return obj;

}


#endregion


posted by 방랑군 2009. 9. 23. 14:24



Understanding Section Handlers - App.config File

참조 : http://www.codeproject.com/KB/aspnet/ConfigSections.aspx


예제 Config

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

//1 SECTIOIN 구성등

<configSections>

<sectionGroup name="settings">

<section name="dbSettings" type="System.Configuration.NameValueSectionHandler"/>

</sectionGroup>

<sectionGroup name="inputScreen">

<section name="education" type="System.Configuration.DictionarySectionHandler"/>

<section name="sex" type="System.Configuration.SingleTagSectionHandler"/>

</sectionGroup>

<sectionGroup name="companyInfo">

<section name="companyAddress" type="ConfigSections.MyConfigHandler,ConfigSections"/>

</sectionGroup>

</configSections>


<settings>

<dbSettings>

<add key="connectionString" value="Data Source=localhost;Initial Catalog=Northwind;"/>

<add key="imagesPath" value="c:\MyApp\Resources\Images\"/>

</dbSettings>

</settings>


<inputScreen>

<education>

<add key="1" value="High School"/>

<add key="2" value="Bachelors"/>

<add key="3" value="Masters"/>

<add key="4" value="Doctorate"/>

</education>

<sex Male="1" Female="2"/>

</inputScreen>


<companyInfo> 

<companyAddress> 

<companyName>Axxonet Solutions India Pvt Ltd</companyName>

<doorNo>1301</doorNo>

<street>13th Cross, Indira Nagar, 2nd Stage</street>

<city>Bangalore</city>

<postalCode>560038</postalCode>

<country>India</country>

</companyAddress>

</companyInfo>


<!--

Read appsettings from an external file.

-->

<appSettings file="appSettings.xml"/>

<appSettings>

<add key="author" value="Palanisamy Veerasingam"/>

<add key="article" value="Configuration Sections"/>

</appSettings>

</configuration>


.NET 1.1 호출 밥법

NameValueCollection nvc=(NameValueCollection)ConfigurationSettings.GetConfig("settings/dbSettings");

            MessageBox.Show("Connection String is " + nvc[0].ToString() );



Hashtable objHash=(Hashtable) ConfigurationSettings.GetConfig("inputScreen/education");

MessageBox.Show("Education list count is " + objHash.Count);


Hashtable objHash=(Hashtable) ConfigurationSettings.GetConfig("inputScreen/sex");

MessageBox.Show("Value of male is " + objHash["Male"].ToString() );

CCompanyAddr obj=(CCompanyAddr)ConfigurationSettings.GetConfig("companyInfo/companyAddress"); 

string strMsg;

strMsg = "Company Address is:\n" +

 "\n" + obj.CompanyName +

 "\n" + obj.DoorNo + ", " + obj.Street +

 "\n" + obj.City + 

     "\n" + obj.Country;

MessageBox.Show(strMsg);



string strAuthor=ConfigurationSettings.AppSettings["author"];

MessageBox.Show("This sample is coded by " + strAuthor);



.NET 2.0... 






posted by 방랑군 2009. 9. 23. 14:19

Using Alternative Configuration Sources

You can also use any XML configuration file or other source of configuration information if required. For example, you can load configuration information into containers from a specific named configuration file by using the .NET Framework System.Configuration.Configuration class to retrieve the information from any XML formatted file. The following code shows how you can read configuration information from a file named MyConfig.config.


클래스 ExeConfigurationFileMap 

namespace System.Configuration

{

    // 요약:

    //     Exe.config 파일의 구성 파일 매핑을 정의합니다. 이 클래스는 상속될 수 없습니다.

    public sealed class ExeConfigurationFileMap : ConfigurationFileMap


참조 : Unity Application Block 1.2 - October 2008 Configuring Containers at Design Time

ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = "MyConfig.config";
System.Configuration.Configuration config 
  = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None); 
UnityConfigurationSection section
  = (UnityConfigurationSection)config.GetSection("unity");
IUnityContainer container = new UnityContainer();
section.Containers["myContainer"].Configure(container);


- Unity Application Block 에서 사용 소스..

 private SysConfiguration OpenConfigFile(string baseName)

        {

            ExeConfigurationFileMap map = new ExeConfigurationFileMap();

            map.ExeConfigFilename = baseName + ".config";

            return ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);

        }





posted by 방랑군 2009. 9. 23. 14:12


[Format of the Unity Configuration File]

  <configSections>

    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />

  </configSections>

- UnityConfigurationSection 클래스에 맞는 Config 구성

UnityConfigurationSection section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;

UnityConfigurationSection 에 매핑해서 활용

    public class UnityConfigurationSection : ConfigurationSection

    {

.

.

ConfigurationSection 이걸 상속함으로써 :IConfigurationSectionHandler 역활 대신한다.
ConfigurationSection 안에 UNITY 만의 구성된 포맷이 정의 되어 있는거 같음...



posted by 방랑군 2009. 9. 23. 13:45


An error occurred creating the configuration section handler for xx 에러 관련

예)
An error occurred creating the configuration section handler for unity: Could not load file or assembly 'Microsoft.Practices.Unity.Configuration' or one of its dependencies. The system cannot find the file specified. (F:\#Document#\[[SPRING.NET]]\[TEMPLETE]\Console_Plural_Genenic\Console_Config\bin\Debug\Console_Config.vshost.exe.Config line 5)

--> 어셈블 등록된 DLL을 못찾아 로딩이 안되어 생긴 문제.
   : 로컬복사를 TRUE로 해서 컴파일 위치에서 하면 된다.
     그리고, FALSE 하면 어셈블 등록된 DLL로 연결된다.


1. 위 예 처럼 Config 의 type 에 선언된 클래스가 로딩이 안된 경우....
   파일 위치를 로컬복사 하던지 어셈블 매핑을 확인한다(어떻게?? ㅋㅋ).


2. 위 1번 빼고 에러메세지 자세히 보면 해결돤다..
    1번도 메세지 보고 가능한데 생각의 전환이 안되 찾지 못한다.. ㅋㅋㅋ
posted by 방랑군 2009. 9. 23. 13:43

 로컬파일에 존재하는 건 제대로 casting 되었는데,
강한 어셈블 DLL 로딩하면 에러가 안나고 "System.Configuration.DefaultSection" 로 CASTING 된다. 
  - 원래 안되었는데 로컬파일 된다음 하니 물려서 된다. 니미(--;)~~.. 근데 잘못 CASTING 된다...
    원래 System.Configuration.DefaultSection 에 매핑되는건지 아님 에러가 나는지 
"Microsoft.Practices.Unity.Configuration.UnityConfigurationSection" 에 CASTING
되는지 확인해보야 하나 그럼 엄청난 삽질과 재설치 테스트를 해야한다.. 그래서, 패스~


  <configSections>

//1) 실행파일 로컬에 존재 해야 함(본인 실행파일이나 DLL)

    <section name="unity2" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />

  </configSections>


//2) 어셈블리에 등록된 DLL 를 호출하는 경우

  <configSections>

    <section name="unity"

              type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,

                 Microsoft.Practices.Unity.Configuration, =1.3.0.0,

                 Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

  </configSections>

.

.

.

  

</configuration>



            Configuration currentConfig =                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

            object config = currentConfig.GetSection("unity2");


            Configuration currentConfig =                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

            object config = currentConfig.GetSection("unity");



'GET > Configuration' 카테고리의 다른 글

사용자가 임의로 만든 any XML configuration file 제어  (1) 2009.09.23
Unity Application Block 에서의 Configuration  (1) 2009.09.23
Error 처리  (0) 2009.09.23
Sample - 1  (0) 2009.09.23
XML Config 제어하기.  (0) 2009.09.23
posted by 방랑군 2009. 9. 23. 13:07




App.config

<?xml version="1.0" encoding="utf-8" ?>

<configuration>


  <configSections>

    <section name="unity" type="Console_Config_User.UserInfo,Console_Config_User" />

  </configSections>


  <unity>

    <NAME>황승재</NAME>

    <ADDRESS>염창동</ADDRESS>

    <HP>016-647-0678</HP>

  </unity>

</configuration>


Console_Config_User.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;


using System.Configuration;


namespace Console_Config_User

{

    class UserInfo : System.Configuration.IConfigurationSectionHandler

    {


        public string _NAME;

        public string _ADDRESS;

        public string _HP;


        public UserInfo()

        {

            _NAME =

            _ADDRESS =

            _HP = "";

            

        }


        #region IConfigurationSectionHandler 멤버


        public object Create(object parent, object configContext, System.Xml.XmlNode section)

        {

            //throw new NotImplementedException();


            UserInfo obj = new UserInfo();


            ///

            /// section.SelectSingleNode("config").InnerText;

            ///

            obj._NAME    = section.SelectSingleNode("NAME").InnerText; // section 이용하여 config 값 넣는다.  

            obj._ADDRESS = section.SelectSingleNode("ADDRESS").InnerText; // section 이용하여 config 값 넣는다.

            obj._HP      = section.SelectSingleNode("HP").InnerText; // section 이용하여 config 값 넣는다.

            return obj;

        }


        #endregion

    }

}


- object parent, object configContext 이거 null 로 들어옴... 


Program.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;


using System.Configuration;


namespace Console_Config_User

{

    class Program

    {

        static void Main(string[] args)

        {


            //object config = ConfigurationManager.GetSection("unity");


            UserInfo container = new UserInfo();

            container = (UserInfo)ConfigurationManager.GetSection("unity");

            

        }

    }

}




posted by 방랑군 2009. 9. 23. 12:46

0. .NET 1.1 ConfigurationSettings.GetConfig("") 와 IConfigurationSectionHandler
    .NET 2.0 ConfigurationManager.GetSection("") 와 IConfigurationSectionHandler

1. App.config, Web.config. machine.config 등 정해진 Config 제어

2. 사용자가 임의로 만든 any XML configuration file 제어

3. Unity Application Block 에서의 Configuration

'GET > Configuration' 카테고리의 다른 글

사용자가 임의로 만든 any XML configuration file 제어  (1) 2009.09.23
Unity Application Block 에서의 Configuration  (1) 2009.09.23
Error 처리  (0) 2009.09.23
Config 의 type 과 DLL 과 연결 관련...  (0) 2009.09.23
Sample - 1  (0) 2009.09.23