지난번 알아보았던 자동구현 프로퍼티(Auto-Implemented Properties)는 그동안 개발자들을 귀찮게 하던 멤버변수와 멤버변수에 대한 엑세스를 지원하는 프로퍼티를 생성하는데 좀 더 간결하게 표현할 수 있도록 해는 것이었다면 이번에 볼 객체와 컬렉션에 대한 이니셜라이저(Object and Collection Initializer)는 객체 또는 컬렉션의 생성을 좀더 직관적으로 할 수 있도록 해줍니다.
C# 2.0까지 객체를 생성할때 객체내의 멤버들을 동적으로 초기화 시키기 위해서는 생성자의 매개변수를 사용하거나, 생성후 객체의 각 멤버에 대해서 직접 값을 할당해주는 방법을 사용하였습니다만, C# 3.0의 Object and Collection Initializer는 생성자의 선언없이도 생성과 동시에 해당 객체나 컬렉션에 대한 초기화가 가능해지는 것입니다. 실제 코드를 보면 쉽게 이해가 가능하실 겁니다.
[코드 1-1 : C# 3.0 이전의 객체 초기화]
1 public class Customer
2 {
3 private int custKey;
4 private string name;
5 private string address;
6
7 public int CustKey { get { return custKey; } }
8 public string Name
9 {
10 get { return name; }
11 set { name = value; }
12 }
13 public string Address
14 {
15 get { return address; }
16 set { address = value; }
17 }
18 }
19
20 public class Program
21 {
22 static void Main(string[] args)
23 {
24 Customer customer = new Customer();
25 customer.Name = "오성민";
26 customer.Address = "서울시 구로구";
27 }
28 }
위의 코드는 언제나 보던 일반적인 코드입니다. 객체를 생성한 후 해당 객체의 멤버에 값을 할당하는 것이죠. 이 코드를 Object and Collection Initializer를 이용한 코드로 바꾼다면 아래와 같이 됩니다.
[코드 1-2 : C# 3.0 의 Object and Collection Initializer를 이용한 초기화
1 public class Customer
2 {
3 public int CustKey { get; private set; }
4 public string Name { get; set; }
5 public string Address { get; set; }
6 }
7
8 public class Program
9 {
10 static void Main(string[] args)
11 {
12 Customer customer = new Customer
13 {
14 Name = "노휘겸",
15 Address = "서울시 관악구"
16 };
17 }
18 }
지난번에 보았던 자동구현 프로퍼티를 이용하여 Customer 클래스를 작성하였고, 이 클래스의 객체를 생성하는 시점에서 Customer객체의 내부 멤버들의 값을 할당하였습니다.
Object and Collection Initializer의 구성은 여러개의 멤버에 대한 이니셜라이저가 ,(콤마)로 구분되어 있으며, 이니셜라이저 외부에는 "{", "}"로 둘러싸여 구성되어 있습니다.
이니셜라이저는 접근이 가능한 멤버나 프로퍼티에 대해서만 값의 할당이 가능합니다.
즉, 위의 코드에서 본다면 set이 private 으로 구성된 CustKey의 경우에는 CustKey = 1 로 할당 할 수 없는 것입니다.
그리고, 한번에 같은 멤버를 두번이상 할당할 시에는 오류가 발생하게 됩니다.
아래는 위보다 조금 복잡한 사용예입니다.
[코드2]
1 public class Point
2 {
3 public int X { get; set; }
4 public int Y { get; set; }
5 }
6
7 public class Line
8 {
9 public Point P1 { get; set; }
10 public Point P2 { get; set; }
11 }
12
13 public class Triangle
14 {
15 private Point p1 = new Point();
16 private Point p2 = new Point();
17 private Point p3 = new Point();
18
19 public Point P1 { get { return p1; } set { p1 = value; } }
20 public Point P2 { get { return p2; } set { p2 = value; } }
21 public Point P3 { get { return p3; } set { p3 = value; } }
22 }
23
24 public class Program
25 {
26 static void Main(string[] args)
27 {
28 Line line = new Line
29 {
30 P1 = new Point { X = 1, Y = 1 },
31 P2 = new Point { X = 4, Y = 4 }
32 };
33
34 Triangle triangle = new Triangle
35 {
36 P1 = { X = 0, Y = 0 },
37 P2 = { X = 5, Y = 5 },
38 P3 = { X = 5, Y = 0 }
39 };
40 }
41 }
위와 같이 이니셜라이저 안에서 또다른 객체의 이니셜라이저가 존재할 수도 있으며, 이미 생성된 객체의 경우에는 값의 할당이 바로 이루어질 수도 있습니다.
line 객체의 경우 P1, P2 Point 객체가 생성되지 않았으므로 new Point {...}으로 생성과 함께 할당을 하였으나, triangle 객체의 경우에는 이미 Point 클래스의 객체들이 이미 생성되어 있으므로 생성하는 부분을 생략하고 바로 값을 할당하고 있음을 볼 수 있습니다.
만일 [코드1-2]에서와 같이 CustKey처럼 외부에서 할당이 불가능하고 생성자의 파라미터를 통해서 값을 할당해야 할때도 사용이 가능할까요?
물론 사용이 가능합니다. 생성자가 있다고 해서 달라질것은 생성자에 파라미터에 해당하는 값을 전송하면 되는 것이죠.
public class Customer
{
public int CustKey { get; private set; }
public string Name { get; set; }
public string Address { get; set; }
public Customer(int custKey)
{
CustKey = custKey;
}
}
Customer customer = new Customer(1) { Name = "노휘겸", Address = "서울" };
만일 생성자에서 값이 할당된 멤버를 다시 이니셜라이저에서 값을 할당하면 이니셜라이저에서 할당한 값으로 설정이 됩니다.
이름이 Object and Collection Initializer 이므로 이제 컬렉션을 이용하는 코드를 보도록 하죠. 다들 예상하시겠지만, Collection이라고 해서 다른게 없이 위의 이니셜라이저 안에서 또 다른 이니셜라이저를 사용하는 것과 동일합니다.
1 List<Customer> customers = new List<Customer>
2 {
3 new Customer(1) { Name = "노휘겸", Address = "서울" },
4 new Customer(2) { Name = "류순필", Address = "마산" },
5 new Customer(3) { Name = "황원준", Address = "오산" }
6 };
Customer객체가 담기는 Generic List의 생성을 한번에 완료시켰습니다. 만일 이 코드를 C# 2.0의 코드로 작성한다면
1 List<Customer> customers = new List<Customer>();
2 Customer customer1 = new Customer(1);
3 customer1.Name = "노휘겸";
4 customer1.Address = "서울";
5 customers.Add(customer1);
6 ......
위와 같은 형태가 되겠죠? 보시는 여러분들이 판단하실 부분이긴 하지만, 제 주관적으로는 상당히 직관적이고 코드 읽기가 수월할 듯 하네요.
지난번 Auto-Implemented Properties 와 이번의 Object and Collection Initializer 의 경우 감탄을 자아낼 만큼 대단한 기능은 아니지만, C#의 언어의 표현력을 향상시켜주는 것 같습니다.
궁금한점이나 지적사항이 있으면 댓글로 남겨주세요.
댓글을 달아 주세요
Acrobat SDK 9를 인스톨 하는데... 비쥬얼스튜디오 2005가 깔려 있어야 된다는 메세지가 나오는군요...
쥔장님 께서는 위의 소스를 2008에서 개발한건지? 아님 2005에서 개발한건지?
2008에서 했다면 어떻게 하셨는지? 궁금합니다.
Acrobat SDK 를 이용하려고 하시는 군요..
저같은 경우에는 컴퓨터에 Acrobat이 설치되어 있는지라, SDK의 설치는 필요가 없었습니다.
그리고, 개발은 Visual Studio 2010에서 진행하였구요.
SDK 설치에 대해서는 테스트후에 다시 답변을 드리도록 하겠습니다.^^;
빠른 답변 감사 드립니다.
Acrobat Reader만 설치된 컴에서는
Acrobat.AcroPDDoc pdfDoc = new Acrobat.AcroPDDoc();
이부분에서 COM Exception이 발생합니다 ㅠ.ㅠ
당췌 어떻게 해야 할지 쩝~~!
PDF --> Image.. 검색을 해보니 상용 패키지 뿐이여서...쩝~!
Reader만 깔린컴에서 Load가 되면.. 이를 이용해서... 이미지를 가져올수 있다 생각했는데.. 쉽지가 않군요...
쥔장님 다른 방법은 없겠습니까?
답변이 조금 늦었네요.
찾아보니, Acrobat Reader는 COM 인터페이스를 노출하지 않으므로 위 코드를 사용할 수가 없겠네요.
위 코드를 실행하기 위해서는 Adobe Acrobat이 설치되어 있어야만 합니다. 내용은 수정해 놓도록 하겠습니다.
원하시는 답변을 못 드려 죄송합니다.
안녕하세요.. pdf에 관해 공부 중인 학생입니다.
다름이 아니라 님 소스 중에서 제가 돌려 보니 계속 이부분에 서 터집니다.ㅠ 왜 그런 지 모르겠습니다.ㅠ
제가 너무 초보라서요.ㅠ
Acrobat.AcroPDDoc pdfDoc = new Acrobat.AcroPDDoc();
그리고 정말 죄송합니다만 pdf에 관련된 자료 같은게 있으면 저한테 메일로 좀 보내주시면 안될까요?!ㅠ
부탁좀드리겠습니다.ㅠ
tjdgnszz7@naver.com
혹시 개발PC에 Acrobat이 설치가 안되어 있지 않나요?
위 방법은 실행하는 PC에 Acrobat이 꼭 설치되어 있어야 합니다.(Adobe Reader 나 Acrobat Reader가 설치되어 있어서는 되지 않습니다.)
음 제 경우에는 클립보드에서 이미지를 가져오는 데서 많은 어려움이 있었습니다. Bitmap이 System.Drawing.Bitmap인가요? 타입 변환이 안 되서 var로 받아온 뒤 살펴보니 BitmapSource더라구요...
근데 3.5이후에는 BitmapSource로 가져오는게 버그가 있다고.. 하네요; 엄청 고생했습니다.
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/10589cd6-6a48-4497-8f7d-a12490f376c6
여기서 링크된 곳 여기 저기 들어가서 결국 해결했죠;
그렇군요.. BitmapSource면 WPF에서 하셨나요?
Windows Forms Project에서 테스트한거라, 그럴지도 모르겠네요.
댓글 감사드립니다.