private static void AddProperty(TypeMeta.TypePropertyMeta property, TypeBuilder builder, Type baseType) { PropertyBuilder propertyBuilder = builder.DefineProperty(property.PropertyName, PropertyAttributes.None, property.PropertyType, null); foreach (var item in property.AttributeMetas) { if (item.ConstructorArgTypes == null) { item.ConstructorArgTypes = new Type[0]; item.ConstructorArgValues = new object[0]; } ConstructorInfo cInfo = item.AttributeType.GetConstructor(item.ConstructorArgTypes); PropertyInfo[] pInfos = item.Properties.Select(m => item.AttributeType.GetProperty(m)).ToArray(); CustomAttributeBuilder aBuilder = new CustomAttributeBuilder(cInfo, item.ConstructorArgValues, pInfos, item.PropertyValues); propertyBuilder.SetCustomAttribute(aBuilder); } MethodAttributes attributes = MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public; MethodBuilder getMethodBuilder = builder.DefineMethod("get_" + property.PropertyName, attributes, property.PropertyType, Type.EmptyTypes); ILGenerator iLGenerator = getMethodBuilder.GetILGenerator(); MethodInfo getMethod = baseType.GetMethod("GetValue").MakeGenericMethod(new Type[] { property.PropertyType }); iLGenerator.DeclareLocal(property.PropertyType); iLGenerator.Emit(OpCodes.Nop); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldstr, property.PropertyName); iLGenerator.EmitCall(OpCodes.Call, getMethod, null); iLGenerator.Emit(OpCodes.Stloc_0); iLGenerator.Emit(OpCodes.Ldloc_0); iLGenerator.Emit(OpCodes.Ret); MethodInfo setMethod = baseType.GetMethod("SetValue").MakeGenericMethod(new Type[] { property.PropertyType }); MethodBuilder setMethodBuilder = builder.DefineMethod("set_" + property.PropertyName, attributes, null, new Type[] { property.PropertyType }); ILGenerator generator2 = setMethodBuilder.GetILGenerator(); generator2.Emit(OpCodes.Nop); generator2.Emit(OpCodes.Ldarg_0); generator2.Emit(OpCodes.Ldstr, property.PropertyName); generator2.Emit(OpCodes.Ldarg_1); generator2.EmitCall(OpCodes.Call, setMethod, null); generator2.Emit(OpCodes.Nop); generator2.Emit(OpCodes.Ret); propertyBuilder.SetGetMethod(getMethodBuilder); propertyBuilder.SetSetMethod(setMethodBuilder); }
//这个方法就是把一个RuntimeModelMeta转换成更接近类结构的TypeMeta对象 private TypeMeta GetTypeMetaFromModelMeta(RuntimeModelMeta meta) { TypeMeta typeMeta = new TypeMeta(); //我们让所有的动态类型都继承自DynamicEntity类,这个类主要是为了方便属性数据的读取,具体代码看后面 typeMeta.BaseType = typeof(DynamicEntity); typeMeta.TypeName = meta.ClassName; foreach (var item in meta.ModelProperties) { TypeMeta.TypePropertyMeta pmeta = new TypeMeta.TypePropertyMeta(); pmeta.PropertyName = item.PropertyName; //如果必须输入数据,我们在属性上增加RequireAttribute特性,这样方便我们进行数据验证 if (item.IsRequired) { TypeMeta.AttributeMeta am = new TypeMeta.AttributeMeta(); am.AttributeType = typeof(RequiredAttribute); am.Properties = new string[] { "ErrorMessage" }; am.PropertyValues = new object[] { "请输入" + item.Name }; pmeta.AttributeMetas.Add(am); } if (item.ValueType == "string") { pmeta.PropertyType = typeof(string); TypeMeta.AttributeMeta am = new TypeMeta.AttributeMeta(); //增加长度验证特性 am.AttributeType = typeof(StringLengthAttribute); am.ConstructorArgTypes = new Type[] { typeof(int) }; am.ConstructorArgValues = new object[] { item.Length }; am.Properties = new string[] { "ErrorMessage" }; am.PropertyValues = new object[] { item.Name + "长度不能超过" + item.Length.ToString() + "个字符" }; pmeta.AttributeMetas.Add(am); } else if (item.ValueType == "int") { if (!item.IsRequired) { pmeta.PropertyType = typeof(int?); } else { pmeta.PropertyType = typeof(int); } } else if (item.ValueType == "datetime") { if (!item.IsRequired) { pmeta.PropertyType = typeof(DateTime?); } else { pmeta.PropertyType = typeof(DateTime); } } else if (item.ValueType == "bool") { if (!item.IsRequired) { pmeta.PropertyType = typeof(bool?); } else { pmeta.PropertyType = typeof(bool); } } typeMeta.PropertyMetas.Add(pmeta); } return(typeMeta); }