/// <summary> /// emits a generic get/set property in which the result returned resides in a hashtable whos key is the name of the property /// </summary> /// <param name="pb">PropertyBuilder used to emit</param> /// <param name="tb">TypeBuilder of the class</param> /// <param name="hash">FieldBuilder of the hashtable used to store the object</param> /// <param name="po">PropertyObject of this property</param> private void emitProperty(TypeBuilder tb,FieldBuilder hash,Setting s,string name) { //to figure out what opcodes to emit, i would compile a small class having the functionality i wanted, and viewed it with ildasm. //peverify is also kinda nice to use to see what errors there are. PropertyBuilder pb = tb.DefineProperty(name,PropertyAttributes.None,s.Value.GetType(),new Type[] {}); Type objType = s.Value.GetType(); MethodBuilder getMethod = tb.DefineMethod("get_"+name,MethodAttributes.Public,objType,new Type[]{}); ILGenerator ilg = getMethod.GetILGenerator(); ilg.DeclareLocal(objType); ilg.Emit(OpCodes.Ldarg_0); ilg.Emit(OpCodes.Ldfld,hash); ilg.Emit(OpCodes.Ldstr,name); ilg.EmitCall(OpCodes.Callvirt,typeof(Hashtable).GetMethod("get_Item"),null); if(objType.IsValueType) { ilg.Emit(OpCodes.Unbox,objType); if(typeHash[objType]!=null) ilg.Emit((OpCode)typeHash[objType]); else ilg.Emit(OpCodes.Ldobj,objType); } else ilg.Emit(OpCodes.Castclass,objType); ilg.Emit(OpCodes.Stloc_0); ilg.Emit(OpCodes.Br_S,(byte)0); ilg.Emit(OpCodes.Ldloc_0); ilg.Emit(OpCodes.Ret); MethodBuilder setMethod = tb.DefineMethod("set_"+name,MethodAttributes.Public,null,new Type[]{objType}); ilg = setMethod.GetILGenerator(); ilg.Emit(OpCodes.Ldarg_0); ilg.Emit(OpCodes.Ldfld,hash); ilg.Emit(OpCodes.Ldstr,name); ilg.Emit(OpCodes.Ldarg_1); if(objType.IsValueType) ilg.Emit(OpCodes.Box,objType); ilg.EmitCall(OpCodes.Callvirt,typeof(Hashtable).GetMethod("set_Item"),null); ilg.Emit(OpCodes.Ret); pb.SetGetMethod(getMethod); pb.SetSetMethod(setMethod); if(s.Description!=null) { ConstructorInfo ci = typeof(DescriptionAttribute).GetConstructor(new Type[]{typeof(string)}); CustomAttributeBuilder cab = new CustomAttributeBuilder(ci,new object[]{s.Description}); pb.SetCustomAttribute(cab); } if(s.Category!=null) { ConstructorInfo ci = typeof(CategoryAttribute).GetConstructor(new Type[]{typeof(string)}); CustomAttributeBuilder cab = new CustomAttributeBuilder(ci,new object[]{s.Category}); pb.SetCustomAttribute(cab); } }
/// <summary> /// Gets the Setting object tied to the string. If there is no Setting object, one will be created with the defaultValue /// </summary> /// <param name="key">The name of the setting object</param> /// <param name="defaultvalue">if there is no Setting object tied to the string, a Setting will be created with this as its Value</param> /// <returns>The Setting object tied to the string</returns> public Setting GetSetting(string key, object defaultvalue) { if(settings[key]==null) { settings[key]=new Setting(defaultvalue,null,null); settings[key].Name=key; } return settings[key]; }
/// <summary> /// Emits a generic get/set property in which the result returned resides /// in a hashtable whose key is the name of the property /// </summary> /// <param name="pb">PropertyBuilder used to emit</param> /// <param name="tb">TypeBuilder of the class</param> /// <param name="hash">FieldBuilder of the hashtable used to store the object</param> /// <param name="po">PropertyObject of this property</param> private void emitProperty( TypeBuilder tb, FieldBuilder hash, Setting s, string name) { // to figure out what opcodes to emit, i would compile a small class // having the functionality i wanted, and view it with ildasm. // peverify is also kinda nice to use to see what errors there are. PropertyBuilder pb = tb.DefineProperty( name, PropertyAttributes.None, s.Value.GetType(), new Type[] {}); Type objType = s.Value.GetType(); MethodBuilder getMethod = tb.DefineMethod( "get_" + name, MethodAttributes.Public, objType, new Type[] {}); ILGenerator ilg = getMethod.GetILGenerator(); ilg.DeclareLocal(objType); ilg.Emit(OpCodes.Ldarg_0); ilg.Emit(OpCodes.Ldfld, hash); ilg.Emit(OpCodes.Ldstr, name); ilg.EmitCall( OpCodes.Callvirt, typeof(Hashtable).GetMethod("get_Item"), null); if (objType.IsValueType) { ilg.Emit(OpCodes.Unbox, objType); if (typeHash[objType] != null) { ilg.Emit((OpCode)typeHash[objType]); } else { ilg.Emit(OpCodes.Ldobj, objType); } } else { ilg.Emit(OpCodes.Castclass, objType); } ilg.Emit(OpCodes.Stloc_0); ilg.Emit(OpCodes.Br_S, (byte)0); ilg.Emit(OpCodes.Ldloc_0); ilg.Emit(OpCodes.Ret); MethodBuilder setMethod = tb.DefineMethod( "set_" + name, MethodAttributes.Public, null, new Type[] { objType }); ilg = setMethod.GetILGenerator(); ilg.Emit(OpCodes.Ldarg_0); ilg.Emit(OpCodes.Ldfld, hash); ilg.Emit(OpCodes.Ldstr, name); ilg.Emit(OpCodes.Ldarg_1); if (objType.IsValueType) { ilg.Emit(OpCodes.Box, objType); } ilg.EmitCall( OpCodes.Callvirt, typeof(Hashtable).GetMethod("set_Item"), null); ilg.Emit(OpCodes.Ret); pb.SetGetMethod(getMethod); pb.SetSetMethod(setMethod); if (s.Description != null) { ConstructorInfo ci = typeof(DescriptionAttribute).GetConstructor(new Type[] { typeof(string) }); CustomAttributeBuilder cab = new CustomAttributeBuilder(ci, new object[] { s.Description }); pb.SetCustomAttribute(cab); } if (s.Category != null) { ConstructorInfo ci = typeof(CategoryAttribute).GetConstructor(new Type[] { typeof(string) }); CustomAttributeBuilder cab = new CustomAttributeBuilder(ci, new object[] { s.Category }); pb.SetCustomAttribute(cab); } }
/// <summary> /// adds a setting to this settings object /// </summary> /// <param name="name">property name</param> /// <param name="val">start value of the property</param> /// <param name="desc">property description</param> /// <param name="category">property category</param> /// <param name="eh">event handler to recieve the PropertyValueChanged event</param> /// <param name="reflect">if true, an internal event handler will be created - the refObj must not be null and the name must be the name of a property of the type that refObj is</param> /// <param name="refObj">the object that will recieve the changed property values</param> public void AddSetting(string name,object val,string desc,string category,ValueChangedDelegate eh, bool reflect,object refObj) { //take out all spaces name = name.Replace(" ",""); settings[name]=new Setting(val,desc,category,eh); if(reflect && refObj!=null) { propObj[name]=new PropObj(refObj,name); this[name].ValueChanged+=new ValueChangedDelegate(reflectEvent); } }