怠azine、反射、属性、動的アセンブリ

怠throughによって得られる経験はほとんどありません



3年前、私は1つの会社で働きました。 プログラマーは4人いました。 1つはビジネスアプリケーションロジックを記述しました。 彼はそれをインターフェースを使って説明しました。 論理接続、依存関係など。私たちのタスクは、これらのインターフェイスを実装し、GUIに接続することでした。 このシステムの主な問題は、関係とパラメーターの構造が絶えず変化することでした。 つまり、私たちは常に編集とリファクタリングに対処しなければなりませんでした。



私は怠け者です。 したがって、考えが来ました-これをどうにかして自動化することは本当に不可能ですか? そして、私は本に座った。



最初のステップ



最初のアイデアは明確でシンプルでした。 インターフェースは別々のファイルに含まれています-なぜそれらを解析して、生成されたクラスでテキストファイルを作成しないのですか。 それで終わった。



残念ながら、それらのソースコードは保存されませんでしたが、見たい人には類似物があります(クラスはデータベースのテーブルに基づいて構築されます)


using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Data; using SV.DataBaseWork; using v2; using System.Data.SqlClient; namespace CreatorDBClasses { class ColumnDB { public ColumnDB(string name, string type) { Name = name; Type = ConvertType(type); } public string Name; public string Type; public string Initial = "null"; public string ConvertType(string tp) { switch (tp) { case "String": Initial = "\"\""; return "string"; case "Double": Initial = "0"; return "double"; case "Boolean": Initial = "false"; return "bool"; case "Int32": Initial = "0"; return "int"; default: Initial = "null"; return tp; } } } /// <summary> ///    CreatorDBWorkClasses /// </summary> public class CreatorClasses { String connStr = null; public CreatorClasses(string table, String ConnectionString = null) { tablename = table; className = "cl_" + tablename; if (string.IsNullOrEmpty(ConnectionString)) connStr = v2_SacuraConstants.ConnectionString; else connStr = ConnectionString; // // TODO:    // } string mBaseClass = "DataBaseWorkBase"; public string BaseClass { get { return mBaseClass; } set { mBaseClass = value; } } string tab = "\t\t"; string className; string sources; public string Sources { get { return sources; } } string tablename; List<ColumnDB> mListColumn = new List<ColumnDB>(); public bool GetSources() { sources = "\tpublic class " + className + (string.IsNullOrEmpty(BaseClass) ? "" : " : " + BaseClass) + ", IDisposable\r\n\t{\r\n"; sources += GetConstructor(); sources += GetProperty(); sources += GetInitFunction(); sources += GetSaveFunction(); sources += GetDeleteFunction(); sources += GetDisposable(); sources += StaticGetList(); sources += GetLastError(); sources += "\t}"; return true; } string GetLastError() { return "#region Error\r\n" + " string mError;\r\n" + " public string lastError\r\n" + " {\r\n" + " get { return mError; }\r\n" + " }\r\n" + "#endregion\r\n"; } string StaticGetList() { return "#region Static_GetList\r\n" + " public static List<"+className+"> GetList(string SQL_WHERE = \"\")\r\n" + " {\r\n" + " List<" + className + "> lst = null;\r\n" + " DataBaseWorkBase db = new DataBaseWorkBase(v2_SacuraConstants.ConnectionString);\r\n" + " if (db.Open())\r\n" + " {\r\n" + " lst = new List<" + className + ">();\r\n" + " SqlCommand sqlcmd = db.CreateSQLCommand();\r\n" + " sqlcmd.CommandText = \"SELECT * \" +\r\n" + " \"FROM "+tablename+" \" + SQL_WHERE;\r\n" + " SqlDataReader reader = sqlcmd.ExecuteReader();\r\n" + " while (reader.Read())\r\n" + " {\r\n" + " " + className + " ord = new " + className + "();\r\n" + " if (ord.InitFromDataReader(reader))\r\n" + " lst.Add(ord);\r\n" + " }\r\n" + " reader.Close();\r\n" + " reader = null;\r\n" + " }\r\n" + " db.Close();\r\n" + " db = null;\r\n" + " return lst;\r\n" + " }\r\n" + "#endregion\r\n"; } string GetDisposable() { return "#region  IDisposable\r\n" + " public override void Close()\r\n" + " {\r\n" + " base.Close();\r\n" + " }\r\n" + "\r\n" + " protected override void Dispose(bool disposing)\r\n" + " {\r\n" + " if (disposing)\r\n" + " {\r\n"+ " Close();\r\n" + " base.Dispose(true);\r\n" + " }\r\n" + " }\r\n" + "#endregion\r\n"; } string GetDeleteFunction() { string con = "#region Delete\r\n"+ tab+"public bool Delete()\r\n"+ tab+"{\r\n"+ tab+" bool result = false;\r\n"+ tab+" try\r\n"+ tab+" {\r\n"+ tab+" SqlCommand sqlcmd = CreateSQLCommand();\r\n"+ tab+" sqlcmd.CommandText = \"DELETE FROM "+tablename+" WHERE ID=@ID\";\r\n"+ tab+" sqlcmd.Parameters.AddWithValue(\"@ID\", m_ID);\r\n"+ tab+" sqlcmd.ExecuteNonQuery();\r\n"+ tab+" result = true;\r\n"+ tab+" }\r\n"+ tab+" catch (System.Exception ex)\r\n"+ tab+" {\r\n"+ tab+" }\r\n"+ tab+" return result;\r\n"+ tab+"}\r\n"+ "#endregion\r\n"; return con; } string GetInitParams() { string pr = ""; int cnt = mListColumn.Count; for (int a = 0; a < cnt; a++) { if (mListColumn[a].Type != "string") pr += tab + tab + mListColumn[a].Type + ".TryParse(reader[" + a.ToString() + "].ToString(), out m_" + mListColumn[a].Name + ");\r\n"; else pr += tab + tab + mListColumn[a].Name +"=reader[" + a.ToString() + "].ToString();\r\n"; } return pr; } string GetInitFunction() { string fn = "#region Init\r\n" + tab + "public bool InitFromDataReader(SqlDataReader reader)\r\n" + tab + "{\r\n" + tab + " try\r\n" + tab + " {\r\n" + GetInitParams() + tab + " }\r\n" + tab + " catch (System.Exception ex)\r\n" + tab + " {\r\n" + tab + " return false;\r\n" + tab + " }\r\n" + tab + " return true;\r\n" + tab + "}\r\n" + tab + "public bool Init(string id)\r\n" + tab + "{\r\n" + tab + " if (string.IsNullOrEmpty(id))\r\n" + tab + " return false;\r\n" + tab + " int t;\r\n" + tab + " int.TryParse(id, out t);\r\n" + tab + " return Init(t);\r\n" + tab + "}\r\n" + tab + "public bool Init(int id)\r\n" + tab + "{\r\n" + tab + " if (!base.Open())\r\n" + tab + " return false;\r\n" + tab + " bool IsLoad = false;\r\n" + tab + " try\r\n" + tab + " {\r\n" + tab + " SqlCommand sqlcmd = CreateSQLCommand();\r\n" + tab + " sqlcmd.CommandText = \"SELECT * \" +\r\n" + tab + " \"FROM " + tablename + " WHERE [ID]=@ID\";\r\n" + tab + " sqlcmd.Parameters.AddWithValue(\"@ID\", id);\r\n" + tab + " SqlDataReader reader = sqlcmd.ExecuteReader();\r\n" + tab + " if (reader.Read())\r\n" + tab + " {\r\n" + tab + " if (!InitFromDataReader(reader))\r\n" + tab + " {\r\n" + tab + " reader.Close();\r\n" + tab + " base.Close();\r\n"+ tab + " return false;\r\n" + tab + " }\r\n" + tab + " IsLoad = true;\r\n" + tab + " }\r\n" + tab + " reader.Close();\r\n" + tab + " }\r\n" + tab + " catch (System.Exception ex)\r\n" + tab + " {\r\n" + tab + " mError = ex.Message;\r\n" + tab + " IsLoad = false;\r\n" + tab + " }\r\n" + tab + " base.Close();" + tab + " return IsLoad;\r\n" + tab + "}\r\n"; fn += "#endregion\r\n"; return fn; } string GetConstructor() { string con = "#region Constructor\r\n" + tab + "public " + className + "(string ConnectionString)\r\n" + tab + "\t: base (ConnectionString)\r\n" + tab + "{\r\n" + tab + "}\r\n" + tab + "public " + className + "()\r\n" + tab + "\t:base(v2_SacuraConstants.ConnectionString)\r\n" + tab + "{\r\n" + tab + "}\r\n" + "#endregion\r\n"; return con; } string GetProperty() { mListColumn.Clear(); string src = "#region Property\r\n"; ////////////////////////////////////////////////////////////////////////// //add property SqlConnection myConnection = new SqlConnection(connStr); SqlDataAdapter myAdapter = new SqlDataAdapter("select * from " + tablename, myConnection); DataSet dataSet = new DataSet(); myConnection.Open(); myAdapter.Fill(dataSet, "tablename"); myConnection.Close(); ConstraintCollection prKey = dataSet.Tables[0].Constraints; for (int i = 0; i < dataSet.Tables[0].Columns.Count; i++) { string tab1 = "\t\t\t"; src += tab; ColumnDB clTp = new ColumnDB(dataSet.Tables[0].Columns[i].ColumnName, dataSet.Tables[0].Columns[i].DataType.Name); mListColumn.Add(clTp); src += clTp.Type + " m_" + clTp.Name +"="+clTp.Initial+ ";\r\n"; src += "\t\t"; src += "public "+clTp.Type + " " + clTp.Name + "\r\n" + tab + "{\r\n" + tab1 + "get\r\n" + tab1 + "{\r\n" + tab1 + "\treturn m_" + clTp.Name + ";\r\n" + tab1 + "}\r\n" + tab1 + "set\r\n" + tab1 + "{\r\n" + tab1 + "\tm_" + clTp.Name + "=value;\r\n" + tab1 + "}\r\n" + tab + "}\r\n"; } ////////////////////////////////////////////////////////////////////////// return src + "#endregion\r\n"; } string GetSaveInsertParams() { string pr = ""; int cnt = mListColumn.Count; for (int a = 1; a < cnt; a++) { pr += tab + tab + tab + (a == 1 ? "\"[" : "\",[") + mListColumn[a].Name + "]\"+\r\n"; } return pr; } string GetSaveInsertValues() { string pr = ""; int cnt = mListColumn.Count; for (int a = 1; a < cnt; a++) { pr += tab + tab + tab + (a == 1 ? "\"@" : "\",@") + mListColumn[a].Name + (a != cnt - 1 ? "\"+\r\n" : ")\""); } return pr; } string GetSaveUpdateParams() { string pr = ""; int cnt = mListColumn.Count; for (int a = 1; a < cnt; a++) { pr += tab + tab + tab + (a == 1 ? "\"[" : "\",[") + mListColumn[a].Name + "]=@" + mListColumn[a].Name + "\"" + (a != cnt - 1 ? "+\r\n" : ""); } return pr; } string GetAddWithValue() { string pr = ""; int cnt = mListColumn.Count; for (int a = 1; a < cnt; a++) { pr += tab + tab + "sqlcmd.Parameters.AddWithValue(\"@" + mListColumn[a].Name +"\", m_"+ mListColumn[a].Name+");\r\n"; } return pr; } string GetSaveFunction() { string con = "#region Save\r\n" + tab + "public bool Save()\r\n" + tab + " {\r\n" + tab + " bool result = false;\r\n" + tab + " try\r\n" + tab + " {\r\n" + tab + " SqlCommand sqlcmd = CreateSQLCommand();\r\n" + tab + " if (m_ID <= 0)\r\n" + tab + " {\r\n" + tab + " sqlcmd.CommandText = \"INSERT INTO " + tablename + " ( \"+\r\n" + GetSaveInsertParams() + tab + " \") VALUES (\"+\r\n" + GetSaveInsertValues() + "+\";SELECT CAST(scope_identity() AS int)\";\r\n" + tab + " }\r\n" + tab + " else\r\n" + tab + " {\r\n" + tab + " sqlcmd.CommandText = \"UPDATE " + tablename + " SET \" +\r\n" + GetSaveUpdateParams() + "+\r\n" + tab + " \" WHERE ID=@ID\";\r\n" + tab + " sqlcmd.Parameters.AddWithValue(\"@ID\", m_ID);\r\n" + tab + " }\r\n" + tab + GetAddWithValue() + "\r\n" + tab + " if (m_ID > 0)\r\n" + tab + " sqlcmd.ExecuteNonQuery();\r\n" + tab + " else\r\n" + tab + " {\r\n" + tab + " object ob;\r\n" + tab + " ob = sqlcmd.ExecuteScalar();\r\n" + tab + " if(ob != null)\r\n" + tab + " int.TryParse(ob.ToString(), out m_ID);\r\n" + tab + " }\r\n" + tab + " }\r\n" + tab + " catch (System.Exception ex)\r\n" + tab + " {\r\n" + tab + " mError = ex.Message;\r\n" + tab + " result = false;\r\n" + tab + " }\r\n" + tab + " return result;\r\n" + tab + " }\r\n" + "#endregion\r\n"; return con; } } }
      
      







問題は解決されたようです。 それでも、ファイル転送、リファクタリングなど、まだ多くの作業がありました。 はい、彼らは何も変えていません。 彼らは、UIの作成とオブジェクトモデルへのバインドに関与していました。



第二段階



ネット上で検索を続けると、Typeクラスの説明に出会い興味を持ち、それについてさらに読みました。 このクラスには多くの興味深い機能があります。 実際、彼のおかげで、クラスに関するすべての情報を完全に入手できます。 コンストラクター、実装されたインターフェイス、プロパティ、変数、関数...完全な情報。 そして、私は彼と実験を始めました、そして、最終的に、私は得ました:



クラス型を操作するためのクラス


 using System; using System.Collections.Generic; using System.Reflection; using System.Threading; namespace SV.Tools { public delegate void AddProp(string name, string val); /// <summary> ///     /// </summary> public struct MetodInfoDouble { public MethodInfo getMetod; public MethodInfo setMetod; } /// <summary> ///         :(     /// </summary> public class ClassesTools { /// <summary> ///        /// </summary> /// <param name="ob"></param> /// <param name="delegateProp"></param> /// <param name="parentName"></param> public static void GetAllPropertyData(object ob, AddProp delegateProp, string parentName = "") { if (ob == null || delegateProp == null) return; PropertyInfo[] propInfo = ob.GetType().GetProperties(); for (int b = 0; b < propInfo.Length; b++) { ParameterInfo[] param = propInfo[b].GetIndexParameters(); if (param.Length == 0 && propInfo[b].CanRead && propInfo[b].Name != "Root" && propInfo[b].Name != "Parent") { object data = propInfo[b].GetValue(ob, null); if (propInfo[b].PropertyType.IsInterface && data != null) { GetAllPropertyData(data, delegateProp, (parentName == "" ? "" : parentName + ".") + propInfo[b].Name); } else { delegateProp((parentName == "" ? "" : parentName + ".") + propInfo[b].Name, ( data == null ? "NULL" : SV.ConversionTools.DataCoversion.ConvertByType(data))); } } } } static AppDomain domain = Thread.GetDomain(); static Assembly[] asm = domain.GetAssemblies(); /// <summary> ///     /// </summary> /// <param name="name"> </param> /// <returns></returns> public static Type FindInterfece(string Namespace, string Name, bool isIgnorCase = true) { if (Namespace == "" || Name == "") return null; int count = asm.Length; for (int a = 0; a < count; a++) { Type t = asm[a].GetType(Namespace+"."+Name); if (t != null) return t; } return null; } public static List<Type> GetAsseblyIntrface(string AssembleName, string Namespace) { if (Namespace == "" ) return null; int count = asm.Length; for (int a = 0; a < count; a++) { if (asm[a].GetName().Name == AssembleName) { Type[] t = asm[a].GetTypes(); List<Type> lst = new List<Type>(); count = t.Length; for(int b =0; b < count; b++) { if (t[b].Namespace == Namespace) lst.Add(t[b]); } return lst; } } return null; } /// <summary> ///   ,  ,   /// </summary> /// <param name="tp"></param> /// <param name="listInterfece"></param> public static void GetAllInterfece(Type[] tp, ref List<Type> listInterfece) { if (tp == null) return; int count = tp.Length; for (int a = 0; a < count; a++) { Type rezult = listInterfece.Find( delegate(Type typ) { return tp[a] == typ; } ); if (rezult == null) listInterfece.Add(tp[a]); Type[] t = tp[a].GetInterfaces(); GetAllInterfece(t, ref listInterfece); } } /// <summary> ///   ,   /// </summary> /// <param name="parentClass"></param> /// <returns></returns> public static List<Type> GetAllInterfece(Type parentClass) { List<Type> listClasses = new List<Type>(); GetAllInterfece(new Type[] { parentClass }, ref listClasses); return listClasses; } /// <summary> ///   ,  ,   /// </summary> /// <param name="parentClass"></param> /// <param name="listInterfece"></param> /// <returns></returns> public static List<Type> GetAllInterfece(Type parentClass, List<Type> listInterfece) { List<Type> listClasses = new List<Type>(); GetAllInterfece(new Type[] { parentClass }, ref listClasses); GetAllInterfece(listInterfece.ToArray(), ref listInterfece); return RemoveDouble(listClasses, listInterfece); } /// <summary> ///     /// </summary> /// <param name="sources"></param> /// <param name="editableList">       sources</param> /// <returns> </returns> public static List<Type> RemoveDouble(List<Type> sources, List<Type> editableList) { for (int a = editableList.Count - 1; a >= 0; a--) { if (sources.Find((Type t) => editableList[a] == t) != null) editableList.RemoveAt(a); } return editableList; } /// <summary> ///       /// </summary> /// <param name="_class"> </param> /// <param name="propertyName"> </param> /// <returns> </returns> /// <remarks> ///   /// </remarks> public static PropertyInfo FindProperty(Type _class, string propertyName) { List<PropertyInfo> allProperty = GetAllProperty(_class); int count = allProperty.Count; PropertyInfo info = null; for (int a = 0; a < count; a++) { if (allProperty[a].Name == propertyName) { info = allProperty[a]; break; } } return info; } public static List<Type> RemoveDouble(List<Type> property) { List<Type> retryList = new List<Type>(); int count = property.Count; for (int a = 0; a < count; a++) { if (retryList.Find((Type inf) => property[a] == inf) == null) retryList.Add(property[a]); } return retryList; } public static List<PropertyInfo> RemoveDouble(List<PropertyInfo> property) { List<PropertyInfo> retryList = new List<PropertyInfo>(); int count = property.Count; for (int a = 0; a < count; a++) { if(retryList.Find( (PropertyInfo inf) =>property[a] == inf ) == null) retryList.Add(property[a]); } return retryList; } /// <summary> ///     ,    /// </summary> /// <param name="interfeceList"> </param> /// <returns> </returns> /// <remarks> ///   /// </remarks> public static List<PropertyInfo> GetAllProperty(Type parent) { List<Type> allTypes = GetAllInterfece(parent); List<PropertyInfo> allProperty = new List<PropertyInfo>(); if (allTypes != null) { int count = allTypes.Count; for(int a =0; a < count; a++) { allProperty.AddRange(allTypes[a].GetProperties(/*BindingFlags.Default*/)); } } return RemoveDouble(allProperty); } /// <summary> ///     /// </summary> /// <param name="name"> </param> /// <returns></returns> public static PropertyInfo GetPropertyByName(object curr, string name, ref object objectIsCall) { if (curr == null) return null; PropertyInfo pI = curr.GetType().GetProperty(name); objectIsCall = curr; if (pI == null) { int t = name.IndexOf('.'); if (t > 0) { string curName = name.Substring(0, t); pI = curr.GetType().GetProperty(curName); if (pI != null) { name = name.Remove(0, t + 1); if (name.Length > 0) { object v = pI.GetValue(curr, null); if (v == null) return null; return GetPropertyByName(v, name, ref objectIsCall); } } } } return pI; } /// <summary> ///        /// </summary> /// <param name="interfeceList">  \</param> /// <param name="propertyInfo">  </param> /// <param name="memberInfo">  </param> /// <param name="fieldInfo">  </param> /// <param name="metodInfo">  </param> /// <param name="eventInfo">  </param> public static void GetInterfaceMetadata(List<Type> interfeceList, ref List<PropertyInfo> propertyInfo, ref List<MemberInfo> memberInfo, ref List<FieldInfo> fieldInfo, ref List<MethodInfo> metodInfo, ref List<EventInfo> eventInfo) { int count = interfeceList.Count; for (int a = 0; a < count; a++) { ////////////////////////////////////////////////////////////////////////// //    PropertyInfo[] propertyIE = interfeceList[a].GetProperties(); propertyInfo.AddRange(propertyIE); EventInfo[] events = interfeceList[a].GetEvents(); eventInfo.AddRange(events); MemberInfo[] membersIE = interfeceList[a].GetMembers(); memberInfo.AddRange(membersIE); FieldInfo[] fieldIE = interfeceList[a].GetFields(); fieldInfo.AddRange(fieldIE); MethodInfo[] metodIE = interfeceList[a].GetMethods(); metodInfo.AddRange(metodIE); } } /// <summary> ///     /// </summary> /// <param name="propertyInfoInterface"></param> /// <returns></returns> public static Dictionary<string, MetodInfoDouble> RemoveDoubleProperty(List<PropertyInfo> propertyInfoInterface) { if (propertyInfoInterface == null) return null; Dictionary<string, MetodInfoDouble> m_doubleList = new Dictionary<string, MetodInfoDouble>(); int count = propertyInfoInterface.Count - 1; for (int a = count; a >= 0; a--) { List<PropertyInfo> fnd = propertyInfoInterface.FindAll( (PropertyInfo inf) => inf.Name == propertyInfoInterface[a].Name); PropertyInfo fullMetod = null; MetodInfoDouble mDouble = new MetodInfoDouble(); mDouble.getMetod = null; mDouble.setMetod = null; if (fnd != null && fnd.Count > 1) { string tmp = ""; for (int b = 0; b < fnd.Count; b++) { tmp += fnd[b].ReflectedType.FullName + "\r\n"; propertyInfoInterface.Remove(fnd[b]); if (fnd[b].CanRead && fnd[b].CanWrite) fullMetod = fnd[b]; else if (fnd[b].CanRead) mDouble.getMetod = fnd[b].GetGetMethod(); else if (fnd[b].CanWrite) mDouble.setMetod = fnd[b].GetSetMethod(); } #if DEBUG //MessageBox.Show("DEBUG:\r\n   : " + fnd[0].Name + "\r\n :\r\n" + tmp); #endif if (fullMetod != null) propertyInfoInterface.Add(fullMetod); else { m_doubleList.Add(fnd[0].Name, mDouble); propertyInfoInterface.Add(fnd[0]); } } } return m_doubleList; } public static bool IsPrimitive(Type t) { if (t == null) return true; if (!t.IsClass && !t.IsInterface || t.IsPrimitive || t.IsEnum || t == typeof(String) || t == typeof(Guid) || t == typeof(DateTime)) return true; return false; } /// <summary> ///         /// </summary> /// <param name="propertyName"> </param> ///<param name="param"> </param> /// <returns>,   null       </returns> static public object GetData(object baseCalss,string propertyName, object[] param = null) { if (baseCalss == null || propertyName == null) return null; object RecalcOb = null; PropertyInfo _PropertyDescriptor = SV.Tools.ClassesTools.GetPropertyByName(baseCalss, propertyName.ToString(), ref RecalcOb); object v = null; if (_PropertyDescriptor != null) v = _PropertyDescriptor.GetValue((RecalcOb == null ? baseCalss : RecalcOb), param); return v; } /// <summary> ///       /// </summary> /// <param name="propertyName"> </param> /// <param name="newPropertyData"> </param> ///<param name="param"> </param> /// <returns>false -    </returns> static public bool SetData(object baseCalss, string propertyName, object newPropertyData, object[] param = null) { if (baseCalss == null || propertyName == null) return false; object RecalcOb = null; PropertyInfo _PropertyDescriptor = SV.Tools.ClassesTools.GetPropertyByName(baseCalss, propertyName, ref RecalcOb); if (_PropertyDescriptor == null) return false; object data = newPropertyData; if (newPropertyData != null && newPropertyData.GetType() != _PropertyDescriptor.PropertyType) data = SV.ConversionTools.DataCoversion.ConvertByType(data.ToString(), _PropertyDescriptor.PropertyType); _PropertyDescriptor.SetValue((RecalcOb == null ? baseCalss : RecalcOb), data, param); return true; } } }
      
      







これで、オブジェクトに関するすべての情報を完全に取得でき、
パラメータ名だけでパラメータとデータを送受信することもできます
  /// <summary> ///         /// </summary> /// <param name="propertyName"> </param> ///<param name="param"> </param> /// <returns>,   null       </returns> static public object GetData(object baseCalss,string propertyName, object[] param = null) { if (baseCalss == null || propertyName == null) return null; object RecalcOb = null; PropertyInfo _PropertyDescriptor = SV.Tools.ClassesTools.GetPropertyByName(baseCalss, propertyName.ToString(), ref RecalcOb); object v = null; if (_PropertyDescriptor != null) v = _PropertyDescriptor.GetValue((RecalcOb == null ? baseCalss : RecalcOb), param); return v; } /// <summary> ///       /// </summary> /// <param name="propertyName"> </param> /// <param name="newPropertyData"> </param> ///<param name="param"> </param> /// <returns>false -    </returns> static public bool SetData(object baseCalss, string propertyName, object newPropertyData, object[] param = null) { if (baseCalss == null || propertyName == null) return false; object RecalcOb = null; PropertyInfo _PropertyDescriptor = SV.Tools.ClassesTools.GetPropertyByName(baseCalss, propertyName, ref RecalcOb); if (_PropertyDescriptor == null) return false; object data = newPropertyData; if (newPropertyData != null && newPropertyData.GetType() != _PropertyDescriptor.PropertyType) data = SV.ConversionTools.DataCoversion.ConvertByType(data.ToString(), _PropertyDescriptor.PropertyType); _PropertyDescriptor.SetValue((RecalcOb == null ? baseCalss : RecalcOb), data, param); return true; }
      
      







それは突破口でした。 テスト構造によってGUIにデータバインディングを行うラッパーが作成されました。 開発速度が大幅に向上しました。 原則として、落ち着くことができます。

しかし、私は怠け者です。



第三段階



そのように、金曜日にバーに座って、ある種の広告サインが目を引きました。 ASMというフレーズがありました...霧の脳はすぐに関連性を失いました。ASM-ASSEMBLERとCommon Intermediate Languageの記憶が表面化し、 IL Disassemblerが続きました。 友人とバーを投げて、私は家に走りましたが、刺激のために数リットルのビールを持参することを忘れませんでした。



クラスILGenerator

自宅で、このクラスの情報を読んだ後、私は気づいた-これはそれだ。



ひねりながら回したい



すべての情報をひとまとめにして、仕事に取りかかりました。



まず最初に、簡単なコードでコンソールプロジェクトを作成します


  interface iT { int i { get; set; } } class cT : iT { int t = 0; public int i { get { return t; } set { t = value; } } } class Program { static void Main(string[] args) { } }
      
      







Ildasm.exe(IL逆アセンブラー)で展開しているものを見ました



ASMコード:




 .class interface private abstract auto ansi ILG.iT { .method public hidebysig newslot specialname abstract virtual instance int32 get_i() cil managed { } // end of method iT::get_i .method public hidebysig newslot specialname abstract virtual instance void set_i(int32 'value') cil managed { } // end of method iT::set_i .property instance int32 i() { .get instance int32 ILG.iT::get_i() .set instance void ILG.iT::set_i(int32) } // end of property iT::i } // end of class ILG.iT .class private auto ansi beforefieldinit ILG.cT extends [mscorlib]System.Object implements ILG.iT { .field private int32 t .method public hidebysig newslot specialname virtual final instance int32 get_i() cil managed { // .maxstack 1 .locals init ([0] int32 V_0) IL_0000: nop IL_0001: ldarg.0 IL_0002: ldfld int32 ILG.cT::t IL_0007: stloc.0 IL_0008: br.s IL_000a IL_000a: ldloc.0 IL_000b: ret } // end of method cT::get_i .method public hidebysig newslot specialname virtual final instance void set_i(int32 'value') cil managed { // .maxstack 8 IL_0000: nop IL_0001: ldarg.0 IL_0002: ldarg.1 IL_0003: stfld int32 ILG.cT::t IL_0008: ret } // end of method cT::set_i .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // .maxstack 8 IL_0000: ldarg.0 IL_0001: ldc.i4.0 IL_0002: stfld int32 ILG.cT::t IL_0007: ldarg.0 IL_0008: call instance void [mscorlib]System.Object::.ctor() IL_000d: nop IL_000e: ret } // end of method cT::.ctor .property instance int32 i() { .get instance int32 ILG.cT::get_i() .set instance void ILG.cT::set_i(int32) } // end of property cT::i } // end of class ILG.cT
      
      







カブを少しひっかいた後、転送されたオブジェクトに基づいて動的オブジェクトを生成するためのクラスを作成しました:基本クラス(any)とインターフェースのリスト:



GitHubのプロジェクトへのリンク



プロジェクトについて少し説明します



オブジェクトプロパティの形成:



ゲット


  void CreatePropertyGetMetod(PropertyInfo property, PropertyBuilder custNamePropBldr, FieldBuilder fieldProperty, object redirectData) { #region GET_METOD //     MethodInfo inf = property.GetGetMethod(); //      if (inf == null) { if (m_doubleList.ContainsKey(property.Name)) inf = m_doubleList[property.Name].getMetod; } //       if (inf != null) { //    MethodBuilder custNameGetPropMthdBldr = m_TypeBuilder.DefineMethod("get_" + property.Name, m_getSetAttr, property.PropertyType, Type.EmptyTypes); //   ILGenerator custNameGetIL = custNameGetPropMthdBldr.GetILGenerator(); System.Reflection.Emit.Label end = custNameGetIL.DefineLabel(); //   custNameGetIL.Emit(OpCodes.Nop); custNameGetIL.Emit(OpCodes.Ldarg_0); //   custNameGetIL.Emit(OpCodes.Ldfld, fieldProperty); //   custNameGetIL.Emit(OpCodes.Ret); //    m_TypeBuilder.DefineMethodOverride(custNameGetPropMthdBldr, inf); //   custNamePropBldr.SetGetMethod(custNameGetPropMthdBldr); } //    ////////////////////////////////////////////////////////////////////////// #endregion }
      
      







セット


 void CreatePropertySetMetod(PropertyInfo property, PropertyBuilder custNamePropBldr, FieldBuilder fieldProperty, object redirectData) { #region SET_METOD //   MethodInfo inf = property.GetSetMethod(); //      if (inf == null) { if (m_doubleList != null && m_doubleList.ContainsKey(property.Name)) inf = m_doubleList[property.Name].setMetod; } if (inf != null) { MethodBuilder custNameSetPropMthdBldr = m_TypeBuilder.DefineMethod("set_" + property.Name, m_getSetAttr, null, new Type[] { property.PropertyType }); ILGenerator custNameSetIL = custNameSetPropMthdBldr.GetILGenerator(); //   custNameSetIL.Emit(OpCodes.Ldarg_0); if (fieldProperty != null) { LocalBuilder loc = custNameSetIL.DeclareLocal(property.PropertyType); custNameSetIL.Emit(OpCodes.Ldfld, fieldProperty); custNameSetIL.Emit(OpCodes.Stloc_0); custNameSetIL.Emit(OpCodes.Ldarg_0); custNameSetIL.Emit(OpCodes.Ldarg_1); //    custNameSetIL.Emit(OpCodes.Stfld, fieldProperty); if (m_baseClass.GetInterface("iMatryoshkaCall") != null) { MethodInfo simpleShow = typeof(iMatryoshkaCall).GetMethod("CallPropertyChange"); //CallPropertyChange(string propertyName, object CommandID = null, object oldData = null, object newData = null) if (simpleShow != null) { custNameSetIL.Emit(OpCodes.Ldarg_0); custNameSetIL.Emit(OpCodes.Ldstr, property.Name); custNameSetIL.Emit(OpCodes.Ldc_I4_0); custNameSetIL.Emit(OpCodes.Box, typeof(int)); custNameSetIL.Emit(OpCodes.Ldloc_0); custNameSetIL.Emit(OpCodes.Box, property.PropertyType); custNameSetIL.Emit(OpCodes.Ldarg_0); custNameSetIL.Emit(OpCodes.Ldfld, fieldProperty); custNameSetIL.Emit(OpCodes.Box, property.PropertyType); custNameSetIL.Emit(OpCodes.Callvirt, simpleShow); } } } custNameSetIL.Emit(OpCodes.Ret); custNamePropBldr.SetSetMethod(custNameSetPropMthdBldr); m_TypeBuilder.DefineMethodOverride(custNameSetPropMthdBldr, inf); } #endregion }
      
      







現在の機能から:



転送されたものに基づいた動的オブジェクトクラスの形成:基本クラスとインターフェイスのリスト、これらのオブジェクトを別のライブラリ(dll)に保存する機能、 Attribute子孫のBuilderClassesPropertyAttribyteを介して、組み込みオブジェクトパラメーターのさまざまな継承と動作を指定できます。 クラスオブジェクトの形成と初期化は、多くのネストされたオブジェクトで実行されます。



私は将来計画します:



いくつかのクラスとインターフェースからオブジェクトを作成する機会を与えるために、C ++の後は本当に見逃しました。



All Articles