글

라벨이 C#인 게시물 표시

C# 에서 SQLite 사용하기 - System.Data.SQLite

이미지
 닷넷 프레임워크에서는 기본적으로 SQLite 를 지원하지 않는 듯 하네요. 이번 포스팅은 C#에서 SQLite를 사용할 수 있게 해주는 System.Data.SQLite 에 대한 것을 정리해 봅니다.   System.Data.SQLite Download 페이지 에 가셔서 각자 개발하고 있는 환경에 맞는 OS 버전과 닷넷 버전용 설치파일을 다운로드 후 설치해줍니다.  진행중인 C# 프로젝트에서 References 마우스 우클릭 -> Add Reference를 선택하신 후 Browse 버튼을 눌러 위와 같이 설치된 System.Data.SQLite.dll 을 참조로 추가해줍니다. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; // SQLite 사용하기 위해 using System.Data.SQLite; namespace SqliteCSharp {     class Program     {         static void Main(string[] args)         {             string strConn = @"Data Source=D:\testdb.db";             using (SQLiteConnection conn = new SQLiteConnection(strConn))             {                 conn.Open(); ...

An unhandled exception of type 'System.BadImageFormatException' occurred in mscorlib.dll

이미지
An unhandled exception of type 'System.BadImageFormatException' occurred in mscorlib.dll Additional information: 파일이나 어셈블리 'System.Data.SQLite, Version=1.0.89.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139' 또는 여기에 종속되어 있는 파일이나 어셈블리 중 하나를 로드할 수 없습니다. 프로그램을 잘못된 형식으로 로드하려고 했습니다.   C#에서 SQLite를 사용 하기 위해 System.Data.SQLite 를 R&D중 위와 같은 오류가 발생했습니다.  진행중인 프로젝트의 Build -> Platform target이 Any CPU로 되어 있다면 DLL에 맞는 버전으로 변경을 해줍니다.  System.Data.SQLite 이외에도 이런 이슈가 있는 것 같네요. 또한 Managed C++ DLL 에서 발생하는 오류인 듯 합니다.

.NET C#에서 자바 JNI 통신하기

이미지
  cocos2d-x에서 안드로이드와 네이티브 C++ JNI 통신 을 해봤었고 유니티3D 안드로이드 플러그인과도 JNI 통신 을 해봤습니다. 이번에는 닷넷 프레임워크 C#과 자바 JNI 통신 해야할 이슈가 생겨서 관련해서 R&D 해본것을 정리해봅니다. Using the Java Native Interface in C# jni4net jnicsharp How to wrap a C# library for use in Java IKVM.NET j-Interop  먼저 자바와 C#간 JNI 처리를 도와주는 모듈들이 위와 같이 몇개 있더군요. 이중에서 제일 위에 있는 것을 가지고 C# 콘솔 어플리케이션에 연동하는 것을 정리합니다.  링크를 클릭하시면 코드프로젝트로 이동하게 되는데 가입하지 않았다면 가입을 하신 후 해당 소스코드를 다운로드 합니다.  JNI.dll 레퍼런스를 얻기위해 적당한 곳에 압축 해제 후 프로젝트를 열어 빌드를 해줍니다.  JNI\Component\bin\Debug 에 JNI.dll이 생성되었습니다. 잠시 후 이것을 C# 콘솔 프로젝트에 추가해야 합니다.  C# 콘솔 프로젝트를 간단히 만드신 후 References 마우스 우클릭 후 Add Reference 를 선택합니다. 위와 같은 다이얼로그 창이 뜨면 Browse를 눌러 좀전에 빌드한 JNI 파일을 지정해줍니다.  OK를 눌러 적용합니다.  마지막으로 다운로드한 소스의 JNI 폴더에 있는 HelloWorld.class 파일을 작업중인 콘솔 프로젝트의 bin\debug에 복사해줍니다. 이 파일은 같이 있는 HelloWorld.java를 컴파일 한 듯하네요. 위 그림에서 오른쪽이 원본 소스고 왼쪽이 작업중인 C# 콘솔 프로젝트입니다.  이것으로 준비작업은 되었구요, 이제 코드 작업입니다. 사실 소스 내용은 샘플 소스와 크게 다르지 않습니다. 윈폼 기반...

error CS0052: Inconsistent accessibility: field type

error CS0052: Inconsistent accessibility: field type `xxx[]' is less accessible than field `yyy.zzz'  해당 C# 컴파일 오류는 오류가 발생하는 xxx 클래스를 만들 때 public 구문을 추가해서 정의하면 됩니다. 즉, class xxx {} 가 아닌 public class xxx {} 이런식으로 말이죠. msdn 컴파일러 오류 CS0052

WCF does not exist in the namespace 'System' (are you missing an assembly reference?)

이미지
Error 1 The type or namespace name 'ServiceModel' does not exist in the namespace 'System' (are you missing an assembly reference?) D:\WCF\WCFConsoleApplication\WCFConsoleApplication\Service1.cs 14 9 WCFConsoleApplication   Svcutil로 만든 WCF 클라이언트 소스 파일 을 C# 콘솔 어플리케이션에서 사용하던중 위와 같은 에러가 발생했습니다. 자동 생성된 코드에는 using System.ServiceModel; 이없네요. 그렇다고 자동 생성된 코드를 수정하면 안되겠죠.  C++의 추가 라이브러리 종속성을 프로젝트 설정에 추가하듯이 C#에서는 레퍼런스(References)라는 곳에 추가를 해줘야하는 듯 싶네요. 위와 같이 기본 생성된 콘솔 어플리케이션에는 System.ServiceModel이 없습니다.  마우스 우클릭 또는 Project 메뉴의 'Add Reference'를 선택합니다.  추가하고자 하는 어셈블리를 검색해서 왼쪽에 체크를 해준 후 OK를 눌러 추가합니다.  어셈블리 레퍼런스가 추가되었습니다.

C# InvalidOperationException: out of sync

InvalidOperationException: out of sync System.Collections.Generic.Dictionary`2+Enumerator[System.String,GameDataTable].VerifyState () (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:912) System.Collections.Generic.Dictionary`2+Enumerator[System.String,GameDataTable].MoveNext () (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:835) System.Collections.Generic.Dictionary`2+KeyCollection+Enumerator[System.String,GameDataTable].MoveNext () (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:1028) GameDataManager.OnApplicationQuit () (at Assets/Script/Kabod/GameDataManager.cs:25)  유니티3D로 작업중 어플을 종료시 위와같이 에러가 발생했습니다. 유니티3D보다는 C#쪽 내용인데요, foreach (string strKey in this.dicGameDataTable.Keys) { RemoveDataTable(strKey); }  게임 종료시 기존에 가지고 있던 Dictionary의 key값에 해당하는 값을 지우려고 시도하다가 발생했습니다. MSDN을 참고해보면 for...

Unity3D GUI.TextField NullReferenceException: Object reference not set to an instance of an object

NullReferenceException: Object reference not set to an instance of an object UnityEngine.TextEditor.ClampPos () UnityEngine.GUI.DoTextField (Rect position, Int32 id, UnityEngine.GUIContent content, Boolean multiline, Int32 maxLength, UnityEngine.GUIStyle style) UnityEngine.GUI.TextField (Rect position, System.String text) TestGUI.OnGUI () (at Assets/TestGUI.cs:37)  이미 비슷한 에러 가 한번 있었는데 이번에는 GUI.TextField 쪽에서 발생하네요. GCMManager.GetInstance().strGCMMsg = GUI .TextField( new Rect ( 0 , fYpos, 300 , 50 ), GCMManager.GetInstance().strGCMMsg);  어디서 메모리 할당 안된 녀석을 참고하나 봤더니, public class GCMManager : MonoBehaviour   { ... public string strGCMMsg;  이게 문제더군요. public string strGCMMsg  = string.Empty;  해주니 되네요.

Unity3D에 쓸만한 JSON C# lib 뭐가 있을까? LitJson

이미지
 지난번에는 cocos2d-x에서 사용할만한 JSON C++ lib를 리서치 했었습니다. 이번에는 Unity3D에서 사용할 JSON C# lib를 리서치해봅니다. C#: fastJSON . JSON_checker . Jayrock . Json.NET - LINQ to JSON . LitJSON . JSON for .NET . JsonFx . JSON@CodeTitans How do I write my own parser? JSONSharp . JsonExSerializer . fluent-json Manatee Json  역시나 JSON 홈페이지 에는 위와같은 링크들이 있습니다. 이중에서 LitJSON 에 대해 정리해봅니다.  이미 상용화된 프로젝트에도 사용이 되었네요. 에어헌터 for Kakao를 만드신 분의 블로그에  LitJson 소개와 간단 사용법  이라고 정리가 되어있습니다. 즉, 유니티3D에서 iPhone과 Android용으로 적용이 가능하다는 말이죠.  설치는 간단합니다. LitJSON 공식홈페이지 에서 최신버전인 litjson-0.7.0을 다운받으셔도 되고 LitJSON의 GitHub 에서 받으셔도 됩니다. 그리고 압축해제 후 bin 디렉터리에 있는 LitJson.dll을 스샷과 같이 Assets\Plugins 안에 복사해줍니다.  유니티3D에서 JSON을 쓸만한 곳은 어디가 있을까요? 여러가지 유용한 부분이 있겠지만 저는  안드로이드와 유니티3D 통신 할 때 사용했던 UnityPlayer.UnitySendMessage의 3번째 인자 때문에 일단 사용하게 되었습니다. 3번째인자로 String뿐이 보낼 수 없으니까요. 페이스북 연동시 친구 리스트를 처리해야하는데 친구 한명한명 보낼수는 없자나요. 그래서 JSON으로 처리하게되었습니다. 관련한 샘플 소스를 보시면, Java JSONArray jsonArr = new JSO...

Unity3D NullReferenceException: Object reference not set to an instance of an

I/Unity(31200):   at TestGUI.OnGUI () [0x00000] in <filename unknown>:0 I/Unity(31200): I/Unity(31200): (Filename:  Line: -1) I/Unity(31200): NullReferenceException: Object reference not set to an instance of an object  아직 생성이 안 되었거나 메모리 할당이 안된 객체에 접근할 때 생기는 오류라고합니다. using System; class Program { static void Main() { string value = null; if (value.Length == 0) // Causes exception { Console.WriteLine(value); // Never reached } } }   dotnetperls.com  의 위와 같은 샘플을 보면 간단히 원인을 파악할 수 있습니다. 제 경우도 위와 비슷했습니다. 페이스북 친구 목록을 안드로이드에서 C#까지 가지고 온 후 GUI에서 C#의 다른 스크립트에 있는 것을 가져와 코루틴을 사용해 친구 이미지를 다운로드하는 부분과 그냥 OnGUI부분에서 Draw해주는 부분에서 잘못된 객체의 접근을 하고 있었네요.

Unity3D C#으로 만든 DLL 사용하기

이미지
  페이스북 C# SDK 를 유니티에 적용하기에 앞서 간단하게 C#으로 만든 DLL lib를 유니티3D에 적용하는 것을 정리해봅니다.  먼저 비주얼 스튜디오로 C# 클래스 라이브러리 프로젝트를 생성합니다. 유니티3D가 .NET Framework 4.5를 지원하는지 모르겠지만 일단 결과 먼저 말씀드리면 잘 되더군요. 물론 간단하게 만들어서 그렇지 100% 호환인지는...  ClassLibrary1프로젝트가 만들어졌습니다. Class1클래스에 간단하게 Hello C# DLL 스트링을 리턴하게 했습니다.  빌드를 한 후 생성된 ClassLibrary1.dll을 유니티3D 프로젝트의 Assets\Plugins에 복사합니다.  유니티3D C# 스크립트를 만들어 스샷과 같이 간단하게 로그를 출력할 수 있게 내용을 추가해줍니다. using 만든dll파일명 으로 사용한다고 알려주고 dll에 있는 클래스로 접근합니다.  메인카메라에 스크립트를 바인드하고 유니티툴에서 실행해보니 잘 작동하네요.

C# 제어가 현재 메서드를 벗어나기 전에 'xxx' out 매개 변수를 할당해야 합니다.

이미지
d:\unityStudy\Part3_6_GUI\Assets\Script\GameDataManager.cs(14,14): Error CS0177: 제어가 현재 메서드를 벗어나기 전에 'gameData' out 매개 변수를 할당해야 합니다. (CS0177) (Assembly-CSharp) d:\unityStudy\Part3_6_GUI\Assets\Script\GameDataManager.cs(3,3): Error CS1502: 'GameDataManager.FindDataTable(string, out IGameData)'에 가장 일치하는 오버로드된 메서드에 잘못된 인수가 있습니다. (CS1502) (Assembly-CSharp) d:\unityStudy\Part3_6_GUI\Assets\Script\GameDataManager.cs(25,25): Error CS1620: '2' 인수는 'out' 키워드를 사용하여 전달해야 합니다. (CS1620) (Assembly-CSharp)  위 로그와 같은 에러가 발생하더군요. C++에서는 인수를 참조등으로 사용하는데 있어 &이나 *를 사용하지만 C#에서는 out , ref 키워드를 사용하네요. 해결은 간단합니다. 함수 호출하는 부분과 함수 정의 부분 모두 out이나 ref를 명시적으로 사용해야 합니다. C#은 명시적인걸 강조하는 모양입니다.  그리고 out으로 된 것은 꼭 해당 변수에 값이 할당되어야 합니다. C++ 처럼 그냥 지나치지는 않는군요.

C# SerializationException: Type xxx is not marked as Serializable.

SerializationException: Type xxx is not marked as Serializable.  유니티3D 프로젝트에 에셋번들 패치 작업 중에 있습니다. 현재 최종 패치된 에셋번들의 이름이나 버젼 정보를 로컬에 저장하기 위해 BinaryFormatter를 가지고 SerDes(직렬화/역직렬화)를 MemoryStream에 하면서 PlayerPrefs에 저장하고 있던 중 제목과 같은 에러가 발생하더군요. public class MyData { ... }  만약 위와같은 클래스를 BinaryFormatter를 통해 직렬화를 한다면 간단히 클래스위에 [Serializable] 이라는 Attribute를 추가해주면 됩니다. [Serializable] public class MyData { ... }  이렇게요. 한가지더, SerializationException: Type xxx in assembly Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null is not marked as serializable.  이런 에러도 발생했는데 제 경우는 public class MyBaseData { ... } public class MyData : MyBaseData { ... }  이렇게 직렬화/역직렬화할 클래스가 상속구조였습니다. 이때는 모두다 [Serializable] 해주면 되더군요.  바이너리로 데이터를 이렇게 쉽게 직렬화/역직렬화 해주다니, 역시 C#은 멋지네요!

C# CS0201 Error. 할당, 호출, 증가, 감소 및 새 개체 식만 문으로 사용할 수 있습니다.

이미지
 C#에서 컴파일 중 '할당, 호출, 증가, 감소 및 새 개체 식만 문으로 사용할 수 있습니다.' 에러가 발생할 수 있습니다. public static string AssetBundleGameDataKeyName = "AssetBundleGameDataSet";  단순 클래스 내부에 이렇게 static 문자열인데 에러가 나더군요. MSDN 을 참고해보니 C#은 위 스샷처럼 단순 해당 변수만 딱 사용하면 안되는 모양입니다. string a = GameDataManager.AssetBundleGameDataKeyName; 또는 GameDataManager.Instance.Add(GameDataManager.AssetBundleGameDataKeyName, assetBundleGameData);  이렇게 다른 변수에 대입해주거나 함수 인자로 넘기거나 등등 해주면 에러는 없어집니다. C++에선 혼자 놀기 되는데 C#은 안되는군요.

C# C++의 Template과 같은 Generic으로 Custom Generic Class 만들어보기

 C++의 템플릿을 C#에서는 제네릭이라고 하네요. 기본적으로 System.Collections.Generic에 있는 Dictionary<,> 등은 자주 사용했는데 커스텀 된 제네릭은 만들어보지 않아서 이번에 유니티3D에서 게임 데이터 시리얼자이즈/디시리얼라이즈 객체 만들면서 필요하게 되서 C#의 커스텀 제네릭 간단한 사용법을 정리해봅니다. 초간단한 내용이므로 C#을 잘 하시는분은 패스하셔도 됩니다.  먼저 간단하게 C++ 템플릿과 C# 제너릭의 차이점을 정리해보면 C# 제네릭이 C++의 템플릿처럼 복잡하지 않고 간편하게 다룰 수 있다가 되겠습니다. C++ 템플릿에서는 지원하는 특징들이 C# 제네릭에서는 사용할 수 없게 제한이 되어있기 때문에 더욱 간편한 듯하네요. 자세한 차이점은 MSDN 링크 를 확인하세요. C++에서는 template<class T> class MyTemplate { ... };  이렇게 했다면, C#은 간단해졌네요. template구문이 필요없네요. class MyTemplate<T> { ... };  이렇게 간단하게 끝내면 섭하죠? 아래는 역시나 MSDN의 제네릭 소개 부분 의 코드를 긁어와 봤습니다. 보통은 아래처럼 안하고 이미 .NET Framework에 있는 LIst<T>를 사용하겠지만 예제니까요. // type parameter T in angle brackets public class GenericList<T> { // The nested class is also generic on T. private class Node { // T used in non-generic constructor. public Node(T t) { next = null ; data = t; ...

Unity3D Error CS0241: 기본 매개 변수 지정자를 사용할 수 없습니다. (CS0241) (Assembly-CSharp-Editor)

이미지
Error CS0241: 기본 매개 변수 지정자를 사용할 수 없습니다. (CS0241) (Assembly-CSharp-Editor)  유니티3D 프로젝트에서 MonoDevelop에서 위와 같은 오류가 발생하며 빌드가 안될 수 있습니다. using UnityEngine; using UnityEditor; public class SysFontEditor : Editor { public static void LookLikeControls(float labelWidth = 70f) { EditorGUIUtility.LookLikeControls(labelWidth); } public static void RegisterUndo(Object obj, string name) { Undo.RegisterUndo(obj, name); EditorUtility.SetDirty(obj); } }  폰트 이슈를 해결하기 위해 리서치 중인 SysFont 패키지를 빌드중에 발생했는데요, 기본적으로 C#에서는 위에서 LookLikeControls(float labelWitdh = 70f) 와 같은 default parameter value를 지원하지 않는다고 합니다. Visual Studio 2008까지는 문법오류가 맞는 듯하고 2010부터는 되는 것 같네요. 확실치는 않습니다.  일단 해결하려면 Tools -> Options에서 제일 밑에 있는 Unity -> Debugger에서 Build project in MonoDevelop를 체크 해제하고 빌드하시면 됩니다. 또한 이것은 Windows 환경에서만 발생하고 Mac에서는 발생하지 않는 에러입니다.

FileSystemWatcher Created 이벤트 처리중 파일의 LastWriteTime이 다른 경우

이미지
 기존에 cocos2d-x용 프로젝트에서 쓸려고 만들었던 패치툴을 유니티3D 게임 프로젝트에 쓸려고 수정중에 있습니다. 예전에는 대충 테스트해서 몰랐는데 지금보니 FileSystemWatcher의 Created 이벤트 발생시 해당 파일의 LastWriteTime 즉, 마시막 수정 날짜가 이상하게 들어오는 증상이 있더군요.             FileInfo curFileInfo = new FileInfo(strFile);             FileInfo descFileInfo = new FileInfo(strDescFile);             if (descFileInfo.Exists == false)             {                 this.MainForm.AddLog("신규 파일 " + strFileWithoutDir);                 return true;             }             else if (curFileInfo.LastWriteTime != descFileInfo.LastWriteTime)             {                 this.MainForm.AddLog("마지막 쓰기 시간 다름 " + strFileWithoutDir);    ...

원격 서버에서 (425) 데이터 연결을 열 수 없습니다. 오류를 반환했습니다

try {      WebClient wc = new WebClient();      wc.Credentials = new NetworkCredential(Id, Pass);                    string strRealServerAddr = Ip + ":" + Port + "/" + RootDir + "/";          wc.UploadFile(strRealServerAddr + strServerFile, strLocalFile);          AddLog("파일 업로드 중..." + strServerFile);      return true; } catch (System.Exception ex) {      iTryCount++;      AddLog("일시적 파일 업로드 에러 : " + ex.Message + " 다시 시도 합니다." + iTryCount.ToString(), true); } 위와 같이 c#의 WebClient로 ftp에 파일 업로드를 하던 중에 '원격 서버에서 (425) 데이터 연결을 열 수 없습니다. 오류를 반환했습니다' 와 같은 예외가 발생할 수 있습니다. MS IIS 상태 코드 설명  링크 밑부분쯤에 가보면 이것은 4xx - 일시적인 부정적 완료 회신 명령이 성공하지 못했지만 오류는 일시적입니다. 클라이언트가 명령을 다시 시도하면 성공할 수도 있습니다. 421 서비스를 사용할 수 없으며 컨트롤 연결을 닫습니다. 이것은 서비스가 프로그램을 종료해야 함을 아는 경우 명령에 대한 응답이 될 수 있습니다. 425 데이터 연결을 열 수 없습니다. 426...

크로스 스레드 작업이 잘못되었습니다. xxx 컨트롤이 자신이 만들어진 스레드가 아닌 스레드에서 액세스되었습니다

이미지
c#으로 개발을 하다보면 '크로스 스레드 작업이 잘못되었습니다. xxx 컨트롤이 자신이 만들어진 스레드가 아닌 스레드에서 액세스되었습니다' 이와 같은 에러가 발생할 수 있습니다. 컨트롤이 있는 스레드가 아닌 다른 스레드에서 컨트롤에 접근을해서 생긴 문제라고 하는데 전 따로 쓰레드를 만들지 않고 툴을 만들다가 폴더의 파일 변화 감지를 자동으로 하려고 FileSystemWatcher를 사용했고 폴더에 변화가 생기면 로그창에 로그를 찍으라고 했는데 이때 InvalidOperationException 예외가 발생하더군요. 내부적으로 등록한 이벤트가 쓰레드로 처리되는가 봅니다. 해결 방법은 크게 3가지가 있습니다. CheckForIllegalCrossThreadCalls = false; 첫번째로 위 한 줄을 추가하면 해결이 가능합니다. 해당 예외는 debug에서만 발생하므로 이 한줄 추가로 예외를 무시할 수 있습니다. 두번째로 delegate와 Invoke를 사용해서 처리합니다. delegate void FileWatcherDelegate(string text); /// <summary> /// 리스트 박스에 로그 출력 /// </summary> /// <param name="strLog"></param> public void AddLog(string strLog) {     try     {         if (this.patchLogList.InvokeRequired)         {             FileWatcherDelegate fileWatcherDelegate = new FileWatcherDelegate(AddLog);            ...