Esempio n. 1
0
        /// <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);
 }
Esempio n. 5
0
 /// <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;
        }