その先にあるもの…

CreateInstance, InvokeMember 본문

프로그래밍/C#

CreateInstance, InvokeMember

specialJ 2014. 4. 21. 11:48

csv로 테이블을 만들어 사용하고 있다.

테이블이 추가 되었고 변경된 테이블도 생겨

테이블 작업을 하다가 수정한 과정을 적어본다.


public class Sound

{

int ID;

string Name;

}


public class SoundTable : Parser

{

Dictionary<int, Sound> map;

}


public class Fx

{

int ID;

string Name;

}


public class FxTable : Parser

{

Dictionary<int, Fx > map;

}


위를 클래스를 매니저에서 변수로 등록하여 사용했다.


public class TableMng

{

private SoundTable m_Sound;

private FxTable       m_Fx;

}


보통 Sound,Fx는 수정되지 않는 상수값이기에 C++에서 const등으로 보호한다.

위의 테이블은 데이터 보호가 되지 않기 때문에 const등으로 보호 접근을 막아보지만

C#에서는 const가 생성자에서 값을 설정하지 못하기 때문에 readonly로 

생성자에 데이터를 넘겨 값을 세팅하여 데이터 변경을 막았다.


public class SoundTable : Parser

{

Dictionary<int, Sound> map;

public override void Parse(string[inputData)
{
Sound sound = new Sound (inputData);
map.Add( sound.ID, sound );
}

}


public class FxTable : Parser

{

Dictionary<int, Fx> map;

Public override void Parse (string [] inputData)
{
Fx fx = new FxinputData );
map.Addfx.IDfx );
}

}


public class TableMng

{

private SoundTable m_Sound;

public SoundTable SOUND{ get{ return m_Sound;} }


private FxTable       m_Fx;

public FxTable FX{ get{ return m_Fx; } }


public void Parse()

{

m_Sound = new SoundTable();

m_Sound.Parse( inputData );


m_Fx= new FxTable       ();

m_Fx.ParseinputData );

}

}


여기서 아이템 테이블이 추가 되었다.

다시 Item, ItemTable을 만들어서 TableMng에 추가 해야하는데
XXXTable은 멤버 변수가 다를 뿐이지 사용법이 동일하다. 그래서 Template로 변경

public class Table<T> : Parser
{
Dictionary< int, T > map;
public override void Parse( string[] inputData )
{
T data = new T(inputData);
map.Add( data.ID, data );
}
}

public class TableMng

{

Table< Sound > m_Sound;

Table< Fx > m_Fx;

Table< Item > m_Item;


public void Parse()

{

m_Sound = new Table<Sound>();

m_Sound.ParseinputData );


m_Fx= new Table<Fx>();

m_Fx.ParseinputData );

}

}


C++처럼 사용하다가 문제가 발생했다.


T data = new T(inputData);
map.Adddata.ID, data );


C++처럼 생성자에 파라미터를 넣어주고
T의 멤버를 호출하게 한 것이 C#에서는 적용될 수 없다.


data.ID를 사용하기 위해서
public interface TableInterface
{
int GetID();
}

public class Sound : TableInterface
{
public int GetID() { return ID; }
}

public class Table<T> : Parser where T : TableInterface, new()
{
Dictionary< int, T > map;
public override void Parsestring[inputData )
{
T data = new T(inputData);
map.Adddata.GetID(), data );
}
}
( dynamic ID로 선언하여 data.ID로 직접 호출을 할 수 있다.하지만 unity에서는 .net버전이 낮아 지원되지 않는다.)

Activator를 이용하여 생성자를 호출할 수 있는 힌트를 얻어

Type type = typeof( T );
T temp = (T)Activator.CreateInstance( type, new object[]{ inputData } );

파라미터를 가진 생성자를 호출하여 새로운 인스턴스를 받아온다.

public class Table<T> : parser where T : TableInterface, new()
{
Dictionary< int, T > map;
public override void Parsestring[inputData )
{
Type type = typeofT );
T temp = (T)Activator.CreateInstancetype, new object[]inputData } );
map.Adddata.GetID(), data );
}
}

data.GetID()를 사용하기 위해서 새로운 table마다 함수를 추가해주어야 한다.
template를 쓰는 의미가 없어지는 것 같아 더 찾아보니

type.InvokeMember를 호출하여 멤버의 데이터를 가져올 수 있다.
public class Table<T> : parser
{
Dictionary< int, T > map;
public override void Parsestring[inputData )
{
Type type = typeofT );
T temp = (T)Activator.CreateInstancetype, new object[]inputData } );
int id = (int)type.InvokeMember( "ID", BindingFlags.Instance|BindingFlags.Public|BindingFlags.GetField,null, temp, null );
map.Add( id, data );
}
}


reflection을 사용하여 부화가 예상되지만 테이블은 초기에 한번 로드되고 테이블을 readonly로 막을 수 있으며
XXXTable을 만들지 않아도 되기 때문에 사용해볼 생각이다.






'프로그래밍 > C#' 카테고리의 다른 글

Dictionary value 변경  (0) 2014.09.01
WeakReference  (0) 2014.06.03
unsafe  (0) 2014.03.28
C#> struct -> string  (0) 2013.10.31
C# delegate  (0) 2013.09.10
Comments