/// <summary> /// Implements the event. /// </summary> /// <param name="engine">The <see cref="CodeGenEngine"/> assembling the type in creation.</param> /// <param name="property">The property to implement.</param> public void Implement(CodeGenEngine engine, GeneratedProperty property) { ILGenerator getMsil = property.GetAccessor.MethodBuilder?.GetILGenerator(); ILGenerator setMsil = property.SetAccessor.MethodBuilder?.GetILGenerator(); // implement get accessor // --------------------------------------------------------------------------------------------------------------- if (getMsil != null) { MethodInfo getValueMethod = typeof(System.Windows.DependencyObject).GetMethod("GetValue", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(System.Windows.DependencyProperty) }, null); getMsil.Emit(OpCodes.Ldarg_0); if (mDependencyProperty.IsReadOnly) { getMsil.Emit(OpCodes.Ldsfld, mDependencyProperty.DependencyPropertyField.FieldBuilder); PropertyInfo dependencyPropertyProperty = typeof(System.Windows.DependencyPropertyKey).GetProperty("DependencyProperty"); getMsil.Emit(OpCodes.Call, dependencyPropertyProperty.GetGetMethod(false)); } else { getMsil.Emit(OpCodes.Ldsfld, mDependencyProperty.DependencyPropertyField.FieldBuilder); } getMsil.Emit(OpCodes.Call, getValueMethod); if (property.Type.IsValueType) { getMsil.Emit(OpCodes.Unbox_Any, property.Type); } getMsil.Emit(OpCodes.Ret); } // implement set accessor // --------------------------------------------------------------------------------------------------------------- if (setMsil != null) { MethodInfo setValueMethod = mDependencyProperty.IsReadOnly ? typeof(System.Windows.DependencyObject).GetMethod("SetValue", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(System.Windows.DependencyPropertyKey), typeof(object) }, null) : typeof(System.Windows.DependencyObject).GetMethod("SetValue", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(System.Windows.DependencyProperty), typeof(object) }, null); setMsil.Emit(OpCodes.Ldarg_0); setMsil.Emit(OpCodes.Ldsfld, mDependencyProperty.DependencyPropertyField.FieldBuilder); if (property.Type.IsValueType) { setMsil.Emit(OpCodes.Box, property.Type); } setMsil.Emit(OpCodes.Call, setValueMethod); } }
/// <summary> /// Implements the event. /// </summary> /// <param name="engine">The <see cref="CodeGenEngine"/> assembling the type in creation.</param> /// <param name="property">The property to implement.</param> public void Implement(CodeGenEngine engine, GeneratedProperty property) { ILGenerator getMsil = property.GetAccessor.MethodBuilder?.GetILGenerator(); ILGenerator setMsil = property.SetAccessor.MethodBuilder?.GetILGenerator(); // implement get accessor // --------------------------------------------------------------------------------------------------------------- if (getMsil != null) { if (property.Kind == PropertyKind.Static) { getMsil.Emit(OpCodes.Ldsfld, mBackingField.FieldBuilder); } else { getMsil.Emit(OpCodes.Ldarg_0); getMsil.Emit(OpCodes.Ldfld, mBackingField.FieldBuilder); } getMsil.Emit(OpCodes.Ret); } // implement set accessor // --------------------------------------------------------------------------------------------------------------- if (setMsil != null) { if (property.Kind == PropertyKind.Static) { setMsil.Emit(OpCodes.Ldarg_0); setMsil.Emit(OpCodes.Stsfld, mBackingField.FieldBuilder); } else { setMsil.Emit(OpCodes.Ldarg_0); setMsil.Emit(OpCodes.Ldarg_1); setMsil.Emit(OpCodes.Stfld, mBackingField.FieldBuilder); } setMsil.Emit(OpCodes.Ret); } }
/// <summary> /// Implements the event. /// </summary> /// <param name="engine">The <see cref="CodeGenEngine"/> assembling the type in creation.</param> /// <param name="property">The property to implement.</param> public void Implement(CodeGenEngine engine, GeneratedProperty property) { ILGenerator getMsil = property.GetAccessor.MethodBuilder?.GetILGenerator(); ILGenerator setMsil = property.SetAccessor.MethodBuilder?.GetILGenerator(); // implement get accessor // --------------------------------------------------------------------------------------------------------------- if (getMsil != null) { if (property.Kind == PropertyKind.Static) { getMsil.Emit(OpCodes.Ldsfld, mBackingField.FieldBuilder); } else { getMsil.Emit(OpCodes.Ldarg_0); getMsil.Emit(OpCodes.Ldfld, mBackingField.FieldBuilder); } getMsil.Emit(OpCodes.Ret); } // implement set accessor // --------------------------------------------------------------------------------------------------------------- if (setMsil != null) { MethodInfo equalsMethod = typeof(object).GetMethod("Equals", new Type[] { typeof(object), typeof(object) }); Label endLabel = setMsil.DefineLabel(); // jump to end, if the value to set equals the backing field if (property.Kind == PropertyKind.Static) { setMsil.Emit(OpCodes.Ldsfld, mBackingField.FieldBuilder); if (property.Type.IsValueType) { setMsil.Emit(OpCodes.Box, property.Type); } setMsil.Emit(OpCodes.Ldarg_0); if (property.Type.IsValueType) { setMsil.Emit(OpCodes.Box, property.Type); } } else { setMsil.Emit(OpCodes.Ldarg_0); setMsil.Emit(OpCodes.Ldfld, mBackingField.FieldBuilder); if (property.Type.IsValueType) { setMsil.Emit(OpCodes.Box, property.Type); } setMsil.Emit(OpCodes.Ldarg_1); if (property.Type.IsValueType) { setMsil.Emit(OpCodes.Box, property.Type); } } setMsil.Emit(OpCodes.Call, equalsMethod); setMsil.Emit(OpCodes.Brtrue_S, endLabel); // update field if (property.Kind == PropertyKind.Static) { setMsil.Emit(OpCodes.Ldarg_0); setMsil.Emit(OpCodes.Stsfld, mBackingField.FieldBuilder); } else { setMsil.Emit(OpCodes.Ldarg_0); setMsil.Emit(OpCodes.Ldarg_1); setMsil.Emit(OpCodes.Stfld, mBackingField.FieldBuilder); } // call event raiser if (property.Kind != PropertyKind.Static) { IMethod raiserMethod = engine.GetMethod("OnPropertyChanged", new Type[] { typeof(string) }); if (raiserMethod == null) { string error = string.Format( "The class ({0}) or its base class ({1}) does not define 'void OnPropertyChanged(string name)'.", engine.TypeBuilder.FullName, engine.TypeBuilder.BaseType.FullName); sLog.Write(LogLevel.Error, error); throw new CodeGenException(error); } if (raiserMethod is GeneratedMethod) { GeneratedMethod method = raiserMethod as GeneratedMethod; setMsil.Emit(OpCodes.Ldarg_0); setMsil.Emit(OpCodes.Ldstr, property.Name); setMsil.Emit(OpCodes.Callvirt, method.MethodBuilder); if (method.ReturnType != typeof(void)) { setMsil.Emit(OpCodes.Pop); } } else if (raiserMethod is InheritedMethod) { InheritedMethod method = raiserMethod as InheritedMethod; setMsil.Emit(OpCodes.Ldarg_0); setMsil.Emit(OpCodes.Ldstr, property.Name); setMsil.Emit(OpCodes.Callvirt, method.MethodInfo); if (method.ReturnType != typeof(void)) { setMsil.Emit(OpCodes.Pop); } } else { throw new NotImplementedException("Method is neither generated nor inherited."); } } setMsil.MarkLabel(endLabel); setMsil.Emit(OpCodes.Ret); } }
/// <summary> /// Reviews the declaration of the property and adds additional type declarations, if necessary. /// </summary> /// <param name="engine">The <see cref="CodeGenEngine"/> assembling the type in creation.</param> /// <param name="property">The property to review.</param> public void Declare(CodeGenEngine engine, GeneratedProperty property) { // add an anonymous field mBackingField = engine.AddField(property.Type, null, property.Kind == PropertyKind.Static, Visibility.Private); }
/// <summary> /// Reviews the declaration of the property and adds additional type declarations, if necessary. /// </summary> /// <param name="engine">The <see cref="CodeGenEngine"/> assembling the type in creation.</param> /// <param name="property">The property to review.</param> public void Declare(CodeGenEngine engine, GeneratedProperty property) { }
/// <summary> /// Initializes a new instance of the <see cref="GeneratedProperty"/> class /// (associates a standard <see cref="System.Windows.PropertyMetadata"/> object with a default value with the dependency property). /// </summary> /// <param name="engine">The code generation engine.</param> /// <param name="name">Name of the property (may be null).</param> /// <param name="type">Type of the property.</param> /// <param name="isReadOnly"> /// true, if the dependency property is read-only; /// false, if it is read-write. /// </param> /// <param name="initializer">A method that provides code creating the default value of the dependency property (may be null to use the type's default value).</param> internal GeneratedDependencyProperty( CodeGenEngine engine, string name, Type type, bool isReadOnly, DependencyPropertyInitializer initializer = null) : base(engine) { mName = name; mIsReadOnly = isReadOnly; // add the dependency property if (mIsReadOnly) { mDependencyPropertyField = (IGeneratedFieldInternal)engine.AddStaticField <System.Windows.DependencyPropertyKey>( name + "Property", Visibility.Public, (msil, field) => { MethodInfo registerReadOnlyMethod = typeof(System.Windows.DependencyProperty).GetMethod( "RegisterReadOnly", BindingFlags.Static, null, new Type[] { typeof(string), typeof(Type), typeof(Type), typeof(System.Windows.PropertyMetadata) }, null); msil.Emit(OpCodes.Ldstr, mName); msil.Emit(OpCodes.Ldtoken, type); msil.Emit(OpCodes.Ldtoken, engine.TypeBuilder); // create PropertyMetadata object ConstructorInfo propertyMetadataConstructor = typeof(System.Windows.PropertyMetadata).GetConstructor(new Type[] { typeof(object) }); if (initializer != null) { initializer(msil, this); } else { CodeGenHelpers.EmitLoadDefaultValue(msil, type, true); } msil.Emit(OpCodes.Newobj, propertyMetadataConstructor); // call DependencyProperty.RegisterReadOnly() method msil.Emit(OpCodes.Call, registerReadOnlyMethod); }); } else { mDependencyPropertyField = (IGeneratedFieldInternal)engine.AddStaticField <System.Windows.DependencyProperty>( name + "Property", Visibility.Public, (msil, field) => { MethodInfo registerMethod = typeof(System.Windows.DependencyProperty).GetMethod( "Register", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(Type), typeof(Type), typeof(System.Windows.PropertyMetadata) }, null); msil.Emit(OpCodes.Ldstr, mName); msil.Emit(OpCodes.Ldtoken, type); msil.Emit(OpCodes.Ldtoken, engine.TypeBuilder); // create PropertyMetadata object ConstructorInfo propertyMetadataConstructor = typeof(System.Windows.PropertyMetadata).GetConstructor(new Type[] { typeof(object) }); if (initializer != null) { initializer(msil, this); } else { CodeGenHelpers.EmitLoadDefaultValue(msil, type, true); } msil.Emit(OpCodes.Newobj, propertyMetadataConstructor); // call DependencyProperty.Register() method msil.Emit(OpCodes.Call, registerMethod); }); } // add the accessor property mImplementation = new PropertyImplementation_DependencyProperty(this); mAccessorProperty = engine.AddProperty( name, type, PropertyKind.Normal, mImplementation); mAccessorProperty.GetAccessor.Visibility = CodeGeneration.Visibility.Public; mAccessorProperty.SetAccessor.Visibility = CodeGeneration.Visibility.Internal; }