データ型クラスのプロパティメンバを、リストのようにインデクサでアクセス出来るようにしたい。
題材
下記のUserInfoクラスのプロパティを、インデクサでアクセス出来るようにする。
classProgram{staticvoidMain(string[]args){varUser=newUserInfo(newList<string>{"012","user","pass","xx@xx.com"});}publicclassUserInfo{publicUserInfo(List<String>userList){ID=userList[0];Name=userList[1];Password=userList[2];email=userList[3];}publicstringID{get;set;}publicstringName{get;set;}publicstringPassword{get;set;}publicstringemail{get;set;}}}前準備 添字でアクセス
classProgram{staticvoidMain(string[]args){varUser=newUserInfo(newList<string>{"012","user","pass","xx@xx.com"});//添字でアクセスUser["ID"]="dummy";if(User.ID=="dummy"){//成功}}publicclassUserInfo{publicUserInfo(List<String>userList){varproperties=typeof(UserInfo).GetProperties();{for(vari=0;i<userList.Count;i++){varname=properties[i].Name;//userListでプロパティをまとめて初期化this[name]=userList[i];}}}publicstringID{get;set;}publicstringName{get;set;}publicstringPassword{get;set;}publicstringemail{get;set;}privatestringthis[stringpropertyName]{get=>typeof(UserInfo).GetProperty(propertyName).GetValue(this).ToString();set=>typeof(UserInfo).GetProperty(propertyName).SetValue(this,value);}}}解説
string this[string propertyName]
このプロパティを追加することで、添字によるアクセスが可能になる。
get
typeof(クラス名).GetProperty(propertyName).GetValue(this)
↑GetValueの戻り値はobject型なので、string型に変換している。
set
typeof(クラス名).GetProperty(propertyName).SetValue(this,value)
コンストラクタ
typeof(UserInfo).GetProperties()クラスのプロパティを配列で取得。properties[i].Name各プロパティ名を取得出来るので、ループ処理が可能になる。
このままだとあまり意味が無いので、インデクサでアクセス出来るようにする。
本番 インデクサでアクセス
下記をUserInfoクラスに追加
privateList<string>NameList;publicstringthis[intnum]{get=>this[NameList[num]];set=>this[NameList[num]]=value;}NameListはプロパティ名一覧が入ったリストとして使います。
string this[int num]
this[string propertyName]をラッパー。NameList[num]でthis[string propertyName]の添字に変換します。
これにより、インデクサでのアクセスが出来るようになります。
全体像
classProgram{staticvoidMain(string[]args){varUser=newUserInfo(newList<string>{"012","user","pass","xx@xx.com"});//添字でアクセスUser["ID"]="dummy";if(User.ID=="dummy"){//成功}Console.WriteLine(User[2]);//passforeach(varname){Console.WriteLine(User.ToList());//012,user,pass,xx@xx.comの順に表示される}}publicclassUserInfo{publicUserInfo(List<String>userList){varproperties=typeof(UserInfo).GetProperties();NameList=newList<string>();//propertiesから、各Name取り出しforeach(var(name,index)inproperties.Select((prop,index)=>(prop.Name,index))){if(index==properties.length-1){//配列の最後はthisプロパティなので、スキップするbreak;}//UserInfoのプロパティ名のリストを作成NameList.Add(name);//全プロパティを初期化this[name]=headerlist[index];}}publicstringID{get;set;}publicstringName{get;set;}publicstringPassword{get;set;}publicstringemail{get;set;}privateList<string>NameList;privatestringthis[stringpropertyName]{get=>typeof(UserInfo).GetProperty(propertyName).GetValue(this).ToString();set=>typeof(UserInfo).GetProperty(propertyName).SetValue(this,value);}publicstringthis[intnum]{get=>this[NameList[num]];set=>this[NameList[num]]=value;}publicList<string>ToList(){varres=newList<string>();NameList.ForEach(name=>res.Add(this[name]));returnres;}}}補足
public List<string> ToList()
thisではリストを返さないため、別途リスト取得用のメソッドを設けています。