/// <summary> /// Python properties may have the following function attributes set to control how they're exposed: /// - _clr_property_type_ - property type (required) /// </summary> /// <param name="propertyName">Property name to add to the type</param> /// <param name="func">Python property object</param> /// <param name="typeBuilder">TypeBuilder for the new type the method/property is to be added to</param> private static void AddPythonProperty(string propertyName, PyObject func, TypeBuilder typeBuilder) { // add the method to call back into python MethodAttributes methodAttribs = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot | MethodAttributes.HideBySig | MethodAttributes.SpecialName; using (PyObject pyPropertyType = func.GetAttr("_clr_property_type_")) { var propertyType = pyPropertyType.AsManagedObject(typeof(Type)) as Type; if (propertyType == null) { throw new ArgumentException("_clr_property_type must be a CLR type"); } PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.None, propertyType, null); if (func.HasAttr("fget")) { using (PyObject pyfget = func.GetAttr("fget")) { if (pyfget.IsTrue()) { MethodBuilder methodBuilder = typeBuilder.DefineMethod("get_" + propertyName, methodAttribs, propertyType, null); ILGenerator il = methodBuilder.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldstr, propertyName); il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("InvokeGetProperty").MakeGenericMethod(propertyType)); il.Emit(OpCodes.Ret); propertyBuilder.SetGetMethod(methodBuilder); } } } if (func.HasAttr("fset")) { using (PyObject pyset = func.GetAttr("fset")) { if (pyset.IsTrue()) { MethodBuilder methodBuilder = typeBuilder.DefineMethod("set_" + propertyName, methodAttribs, null, new[] { propertyType }); ILGenerator il = methodBuilder.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldstr, propertyName); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Call, typeof(PythonDerivedType).GetMethod("InvokeSetProperty").MakeGenericMethod(propertyType)); il.Emit(OpCodes.Ret); propertyBuilder.SetSetMethod(methodBuilder); } } } } }