'Language/C#'에 해당되는 글 5건

  1. 2008/04/10 귀차니스트 RCW 에러의 원인 - ??? (2)
  2. 2008/04/07 귀차니스트 C# Application - Main 에서 Try-Catch 오작동 해결하는 방법 (7)
  3. 2008/03/21 귀차니스트 C# Generics - Generics 문법의 사용법
  4. 2008/03/18 귀차니스트 Systeml.Xml in C# - C#에서 Xml 사용하는 방법
  5. 2008/03/17 귀차니스트 C# As Casting - 새로운 캐스팅 방법 (1)

RCW 에러의 원인 - ???

Language/C# 2008/04/10 11:59 귀차니스트

  오늘 회사에서 옆에서 저와 같이 일하는 형이 C#에서 프로젝트를 하는데 있어서 문제가 생기더군요. 그 원인은 바로 COM 개체를 C# UserControl 로 Wrapping 한 뒤, 그 프로젝트에서 UserControl을 등록하여 폼에 위지윅 배치를 할 경우 "RCW개체에서 분리된 COM개체는 사용할 수 없습니다" 와 비슷한 에러가 뜨는 것이었습니다.
  그래서 집에 와서 대충 한 번 살펴보긴 했는데. 테스트 대상은 Windows Media Player 이었죠. 이것은 문제가 없더군요. 그래서 제가 임의로 추측하기론 멀티쓰레드를 고려하지 않은 즉, Thread-Safe하지 않은 Com 개체에 있어서는 에러가 생긴다고 판단하였습니다.
  실제로 Com 개체의 코드를 보면 대충 이렇게 구현이 되어있죠.

ComExample.cpp (Language : cpp)
  1. #pragma once
  2. #include "resource.h"       // 주 기호입니다.
  3. #include <boost/function.hpp>
  4. #include <string>
  5. #include <stack>
  6. #include <cmath>
  7. #include <map>
  8. #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
  9. #error "단일 스레드 COM 개체는 전체 DCOM 지원을 포함하지 않는 Windows Mobile 플랫폼과 같은 Windows CE 플랫폼에서 제대로 지원되지 않습니다. ATL이 단일 스레드 COM 개체의 생성을 지원하고 단일 스레드 COM 개체 구현을 사용할 수 있도록 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA를 정의하십시오. rgs 파일의 스레딩 모델은 DCOM Windows CE가 아닌 플랫폼에서 지원되는 유일한 스레딩 모델이므로 'Free'로 설정되어 있습니다."
  10. #endif
  11. // CCCalculator
  12. class ATL_NO_VTABLE CCCalculator :
  13.     public CComObjectRootEx<CComSingleThreadModel>,
  14.     public CComCoClass<CCCalculator, &CLSID_CCalculator>,
  15.     public IDispatchImpl<ICCalculator, &IID_ICCalculator, &LIBID_IPangYaLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
  16. {
  17. public:
  18.     CCCalculator()
  19.     {
  20.     }
  21. DECLARE_REGISTRY_RESOURCEID(IDR_CCALCULATOR)
  22. BEGIN_COM_MAP(CCCalculator)
  23.     COM_INTERFACE_ENTRY(ICCalculator)
  24.     COM_INTERFACE_ENTRY(IDispatch)
  25. END_COM_MAP()
  26.     DECLARE_PROTECT_FINAL_CONSTRUCT()
  27.     HRESULT FinalConstruct()
  28.     {
  29.         return S_OK;
  30.     }
  31.     void FinalRelease()
  32.     {
  33.     }
  34. };
  35. OBJECT_ENTRY_AUTO(__uuidof(CCalculator), CCCalculator)

  위에서 보는 코드와 비슷한 Com Object Class 들에서 static 코드가 존재하는 Com 개체였기에 해당 에러가 발생하지 않았나 생각합니다.
  그런데 신기한건 VS.net 2003 에서는 또 별다른 문제가 없이 작동하는 Wrapping 방법이었다는 점이죠. 이 역시 아마 VS.net 2005 로 넘어가면서 IDE 자체의 큰 변화가 있었고, 작동방법이 다르게 구현이 되었기 때문이지 않을까 생각합니다.
  막연한 추측이긴 합니다만 공통된 주제를 가지고 다음에도 토론이 되었으면 하고 포스팅을 합니다.

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/04/10 11:59 2008/04/10 11:59
TAG , ,

댓글을 달아 주세요

  1. kkamagui 2008/04/21 09:27  댓글주소  수정/삭제  댓글쓰기

    쿠아~ 그런 문제도 있구나~
    완전 어렵네... ㅜ_ㅜ... 천지 이래가되긋나 ㅜ_ㅜ

  오늘 정말 희한한 현상을 겪게 되었습니다. 그게 뭐냐하면 바로 C#의 Main단에서 Try-Catch 구문을 걸었는데 제대로 Catch가 걸리지 않았던 것이죠. 그 때는 참 황당했습니다. 왜냐구요? Visual Studio.Net을 C++개발자 타입으로 설정하였을 때, 디버그 모드로 프로세스를 실행하면 Catch까지 잘 걸리는데, 단독 프로세스로 실행했을 경우엔 Catch에 제대로 걸리지 않더군요. Application.Run 내부적으로 처리하는 것 같았습니다.

Program.cs (Language : csharp)
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Windows.Forms;
  5. namespace WindowsFormsApplication3
  6. {
  7.     static class Program
  8.     {
  9.         /// <summary>
  10.         /// The main entry point for the application.
  11.         /// </summary>
  12.         [STAThread]
  13.         static void Main()
  14.         {
  15.             try
  16.             {
  17.                 Application.EnableVisualStyles();
  18.                 Application.SetCompatibleTextRenderingDefault(false);
  19.                 Application.Run(new Form1());
  20.             }
  21.             catch
  22.             {
  23.                 MessageBox.Show("테스트 Catch");
  24.             }
  25.         }
  26.     }
  27. }

Form1.cs (Language : csharp)
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. namespace WindowsFormsApplication3
  10. {
  11.     public partial class Form1 : Form
  12.     {
  13.         public Form1()
  14.         {
  15.             InitializeComponent();
  16.         }
  17.         private void button1_Click(object sender, EventArgs e)
  18.         {
  19.             string aa = null;
  20.             aa.Substring(0);
  21.         }
  22.     }
  23. }

  코드는 대충 위와 같았습니다. Program.cs 에서 Application.Run으로 폼을 표시하고 내부적으로 메시지 펌핑(?)을 하게 될거라 생각을 한 후, Form1에서는 고의적으로 익셉션을 발생시키게 하였습니다. 여기서 바로 문제가 발생합니다. 어떤 거냐구요? Debug 모드로 실행을 한 번 해보시고, 단독 모드로 실행을 한 번 해보십시오. 단독으로 실행을 하면 C#의 기본 Exception MessageBox(?)가 뜰거에요. 절대 메시지 박스가 뜨지 않습니다.
  그래서 결국 구글링을 하다가 찾게 된 페이지에서 하나의 해결책을 발견하고 적용시켜보니 제대로 작동이 되었습니다.


  찾은 코드를 한 번 적용 시켜 보겠습니다. 그럼 Program.cs에 존재하는 코드에 한 줄이 추가됩니다.

Program.cs (Language : csharp)
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Windows.Forms;
  5. namespace WindowsFormsApplication3
  6. {
  7.     static class Program
  8.     {
  9.         /// <summary>
  10.         /// The main entry point for the application.
  11.         /// </summary>
  12.         [STAThread]
  13.         static void Main()
  14.         {
  15.             try
  16.             {
  17.                 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
  18.                 Application.EnableVisualStyles();
  19.                 Application.SetCompatibleTextRenderingDefault(false);
  20.                 Application.Run(new Form1());
  21.             }
  22.             catch
  23.             {
  24.                 MessageBox.Show("테스트 Catch");
  25.             }
  26.         }
  27.     }
  28. }

  Application.SetUnhandledExceptionMode를 ThrowException으로 설정하도록 하니 단독 모드에서도 테스트 Catch 메시지 박스 코드가 존재하는 Catch가 걸립니다. 아마도 추측하기론 Run 내부에서 Try-Catch를 설정하는 듯도 보이는 군요. 30분 정도 이 것때문에 삽질을 하긴 했지만 다음에 이런 일이 발생했을 때는 아주 유용할 것이라 생각합니다.^^

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/04/07 20:49 2008/04/07 20:49

댓글을 달아 주세요

  1. kkamagui 2008/04/09 10:24  댓글주소  수정/삭제  댓글쓰기

    오~ 꽤나 괜찮은 정보네~ ;)

    블로그의 질이 갈수록 높아지는구나 @0@)/~ 홧팅이다~

  2. 준호씨 2008/04/09 16:22  댓글주소  수정/삭제  댓글쓰기

    뭐냐뇽 ㅡ_ㅡ;
    오작동 미워요;

  3. 준호씨 2009/11/23 14:53  댓글주소  수정/삭제  댓글쓰기

    C# 예외처리 찾다가 다시 오게 되는구만 ㅋ
    그나전 C# 쓰면 쓸수록 뭔가 이상하노 -_-; 내가 아직 적응을 못한건감...

    • 귀차니스트 2009/11/25 04:59  댓글주소  수정/삭제

      무엇이 말이삼??
      java 에서 checked-exception 인가??
      throw 로 지정하는거 그건 안되지 싶어 ㅋㅋ

      전체는 그냥 Exception 으로 받아서 하면 될거고..
      Exception을 Inherit 받아서 override 해줌 너만의 Exception 이 되지 않을까..

  4. 준호씨 2009/11/26 00:32  댓글주소  수정/삭제  댓글쓰기

    Java한참 쓰면서.. C#이 Java랑 비슷할거라 생각을 했었는데 여엉 이상하넹 -_-;
    예를 들어
    lblBankName.Text = (String)dr["bankname"];
    이런식으로.. Getter, Setter 도 잘 사용안하고 ToString() 이런거 안쓰고 (String)으로 type을 바꾼다거나 ["bankname"] 처럼 이상한 형식으로 배열을 사용한다거나 -_-; 암튼 구질구질 허구만...
    자바였다면
    lblBankName.SetText(dr.getString("bankname";)); 이런식으로 코딩 했겠지
    예외는 아직 많이 안써봐서 좀 더 써보고 평가 해 볼 수 있을듯 함.

C# Generics - Generics 문법의 사용법

Language/C# 2008/03/21 23:29 귀차니스트

  C++을 다루어보았고, 어느정도 고급쪽의 기술을 알게된다면 Template라는 것을 사용해보셨을 겁니다. 개념상 기존의 프로그래밍과 다른 패러다임을 띄고 있고 데이터표현의 완전성을 지니기 때문에 새로운 것이죠. 그럼 Generics 라는 것은 혹시 들어보셨는지 모르겠습니다. Generics는 Java나 .Net 환경에서 지원하는 새로운 문법입니다. Template보다는 제약이 심하고, 컴파일러 측면에서 지원해주는 그런 문법입니다. 역시 말만 해서는 알아듣기 힘들겠죠??

Generics.cs (Language : csharp)
  1. public class Xml<T>
  2. {
  3. }

  다음과 같이 사용한다면 해당 Xml클래스 내부에서는 T 형을 데이터 타입으로 취하는 개체를 생성하여 사용할 수 있습니다. 바로 Template와 동일하죠. 대신 많은 부분에서 C++ Template와 동일한 기능들을 제공하지는 않습니다. 그리고 template< typename T >와 같은 키워드를 사용하지 않고도 <T>만 붙여줘도 Generics기능이 작동하게 됩니다. 그런데 한 가지 추가적인 기능이 존재하죠. T에 대한 데이터 타입의 제한을 걸어버릴 수 있죠.

Where.cs (Language : csharp)
  1. public class A
  2. {
  3. }
  4. public class B
  5. {
  6. }
  7. public class Xml<T> : XmlLayer where T : A
  8. {
  9. }

  위와 같은 where T : A 라는 조건을 달아줄 경우 T의 데이터 타입은 A 혹은 A에서 파생된 개체로 제한이 걸리게 됩니다. 만약 다른 타입을 넣으려고 한다면 컴파일러 자체에서 지정할 수 없는 형태라고 에러가 발생하죠. 이 방법을 사용하면 데이터 타입을 제한하고자 할 때는 원하는 목적만큼 코딩을 수행할 수 있게 됩니다. 특히 라이브러리를 개발하는 쪽에서는 그 라이브러리를 사용하는 쪽이 한 가지의 방법 외 다른 방향으로 빠지지 않도록 도와주어야 하는데, 이러한 부분에서 도움을 주게 되는 것이죠. 약간은 부족할 지도, 편리할지도 모르는 문법이지만 어느 것이나 그렇듯이 잘 사용한다면 아주 강력한 무기가 될 수 있겠죠^^

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/03/21 23:29 2008/03/21 23:29
TAG , ,

댓글을 달아 주세요

  C++ 에서는 MSXML Parser SDK 를 별도로 깔아 사용하고, GDI Plus 를 깔아 사용했던 것과는 달리 C++.Net 을 비롯한 C#, 즉 .Net 환경에서는 기본적인 네임 스페이스로 위 기능들이 지원됩니다. 어떻게 하냐구요. 물론 시중에 나와있는 책 들도 많습니다. 하지만 최근에 일하는 도중 XML을 이용한 Data Serialization, Deserialization을 구현하다 보니 그냥 자료정리겸 남겨봅니다.
  일단 System.Xml 네임스페이스를 프로젝트에 참조로 추가하고 System.Xml. 네임스페이스를 입력하게 되면 VS.net 의 인텔리 센스가 작동하여 코드가 표시되는데 대부분의 접두어가 Xml 입니다. 종류도 많습니다. XmlNode, XmlElement, XmlText 등 그런데 실제로 해당 객체를 생성하고하면 생성이 되지 않습니다. 그럼 어떻게 생성을 하여야 할까요?

Test.cs (Language : csharp)
  1. private void test()
  2. {
  3.     System.Xml.XmlDocument Doc = new System.Xml.XmlDocument();
  4.     System.Xml.XmlElement Elem = Doc.CreateElement("String");
  5.     Doc.AppendChild(Elem);
  6.     Doc.Save("a.xml");
  7. }

  위와 같은 코드를 사용하시면 됩니다. Document 에서 멤버 메소드로 CreateElement 를 호출하시면 되죠. 이와 비슷하게 CraeteAttribute 같은 함수를 사용하시면 추가적으로 모든 요소를 생성하실 수 있습니다. 그리고 AppendChild 를 호출하게 되면 자기 자신의 자식으로 속성을 추가하게 되죠. 물론 XmlAttribute 이나 XmlText 이냐에 따라서 Save시의 결과물 값이 달라지게 됩니다. 무작정 자식노드로 추가하지는 않는다는 말이죠.
  그럼 반대로 읽어오는 것은 어떻게 하면 될까요??

Load.cs (Language : csharp)
  1. private void button1_Click(object sender, EventArgs e)
  2. {
  3.     System.Xml.XmlDocument Doc = new System.Xml.XmlDocument();
  4.     Doc.Load("a.xml");
  5. }

 아주 간단합니다. Load 라는 메소드를 사용하면 해당 Xml 파일에 대해서 내부적인 파싱을 하여 데이터를 가지고 있게 됩니다. 물론 형태는 XML 형태를 준수하여야 겠죠. 그리고 내부 사용은 Doc.ChildNodes 들을 가지고 자식으로 노드를 타고 내려가며 처리를 하면 됩니다.
  한 때 XML이 인기가 많았던 적이 있었는데 지금은 영 말이 아닌것 같습니다. 그래도 꽤 쓸만한 것이다 보니 유용하게 사용할 부분도 많을것 같네요.

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/03/18 23:59 2008/03/18 23:59

댓글을 달아 주세요

C# As Casting - 새로운 캐스팅 방법

Language/C# 2008/03/17 23:48 귀차니스트

  회사에서 하는 일이 C#으로 클라이언트들의 프로그램을 개발하는 일이다 보니 학교에서 조금 배웠던 C#을 어느정도 능숙하게 다룰 수 있겠 되었습니다. 그러다 보니 꽤나 색다른 방법들도 알게 되더군요. 바로 캐스팅부분이라고 할 수 있습니다.

Casting.c (Language : c)
  1. int main( int argc, char **argv )
  2. {
  3.     int a = 10;
  4.     double b = ( double )a;
  5.     return 0;
  6. }

  몇몇을 제외한 보통의 대학들이나 시중에서 처음 시작하는 언어가 대부분 C 언어이기 때문에 위와 같은 형 변환 구문을 자주 보셨을 겁니다. 하지만 () 를 자주 사용하여 형 변환을 하다보니 코드의 가독성이 떨어지는 등의 단점이 적지 않게 있죠.

Casting.cpp (Language : cpp)
  1. int main( int argc, char **argv )
  2. {
  3.     int a = 10;
  4.     double b = static_cast< int >( a );
  5.     return 0;
  6. }

  그래서 C++ 에서는 캐스팅을 보다 쉽게(?) 읽기 위하여 static_cast, const_cast, reinterpret_cast, dynamic_cast 등을 사용하여 형 변환 하게 됩니다. 형식이 한 가지의 형 변환 형식에서 탈피한 여러가지 방식을 문자를 통하여 보여주고 있으므로 C방식의 형 변환 보다는 판독하기가 쉽습니다.
  이렇게 언어들이 계속 사용되면서 차츰차츰 발전되어왔는데요. 그럼 C# 에서는 형 변환을 어떻게 할까요?

Casting.cs (Language : csharp)
  1. class TempClass {
  2. .
  3. .
  4. .
  5. 생략
  6. }
  7. class TempClass2 : TempClass {
  8. .
  9. .
  10. .
  11. 생략
  12. }
  13. public int Convert()
  14. {
  15.     int a = 10;
  16.     int b = ( int )a;   
  17.     return 0;
  18. }
  19. public int Convert2()
  20. {
  21.     TempClass Cls = null;
  22.     TempClass2 Cls2 = new TempClass();
  23.     Cls = Cls2 as TempClass;
  24.     return 0;   
  25. }

  바로 As 를 사용한 캐스팅이 문법에 추가되었기 때문에 이를 이용하는 방법이 주로 사용되죠, 하지만 이 방법은 값 형식에는 적용되지 않으므로 그 때엔 기존의 () 를 이용한 형 변환이 사용됩니다. 그런데 그냥 코드를 보면 그다지 이익이 보이는 것 같지 않죠?
  하지만 한 가지 이익은 있다고 볼 수 있습니다. () 를 이용한 형 변환을 하게 될 때는 컴파일상 코드에 있어서 많은 부분에 대해서 테스트를 거치지 않게 되고 런타임상 에러가 발생하게 된다면 InvalidCastException이 발생하게 됩니다.
  그러나 as 를 이용하면 InvalidCastException이 일어나지 않고 NULL값으로 초기화 된다고 하는군요. 나름 쓸만한 기능이라고 생각을 하긴 합니다. 사실 그다지 다르다고 느끼는 점은 없지만요. 제가 C# 보다는 C++에 너무 익숙해져 있어서 그럴지도 모르겠습니다. 그래도 많은 부분이 달라진 것들이 차츰차츰 개선되어서 추가되고 하겠죠. 이러한 방법이 있다는 것도 알고 사용했으면 합니다.

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/03/17 23:48 2008/03/17 23:48

댓글을 달아 주세요

  1. 배만토토로 2009/02/16 15:39  댓글주소  수정/삭제  댓글쓰기

    아주 유요한 정보네요
    감사합니다