예제 #1
0
        private void ExtractTemplateValuesRecursive(ArrayList subBuilders, OrderedDictionary table, Control container)
        {
            foreach (object subBuilderObject in subBuilders)
            {
                ControlBuilder subBuilderControlBuilder = subBuilderObject as ControlBuilder;
                if (subBuilderControlBuilder != null)
                {
                    ICollection entries;
                    // filter out device filtered bound entries that don't apply to this device
                    if (!subBuilderControlBuilder.HasFilteredBoundEntries)
                    {
                        entries = subBuilderControlBuilder.BoundPropertyEntries;
                    }
                    else
                    {
                        Debug.Assert(subBuilderControlBuilder.ServiceProvider == null);
                        Debug.Assert(subBuilderControlBuilder.TemplateControl != null, "TemplateControl should not be null in no-compile pages. We need it for the FilterResolutionService.");

                        ServiceContainer serviceContainer = new ServiceContainer();
                        serviceContainer.AddService(typeof(IFilterResolutionService), subBuilderControlBuilder.TemplateControl);

                        try {
                            subBuilderControlBuilder.SetServiceProvider(serviceContainer);
                            entries = subBuilderControlBuilder.GetFilteredPropertyEntrySet(subBuilderControlBuilder.BoundPropertyEntries);
                        }
                        finally {
                            subBuilderControlBuilder.SetServiceProvider(null);
                        }
                    }

                    string  previousControlName = null;
                    bool    newControl          = true;
                    Control control             = null;

                    foreach (BoundPropertyEntry entry in entries)
                    {
                        // Skip all entries that are not two-way
                        if (!entry.TwoWayBound)
                        {
                            continue;
                        }

                        // Reset the "previous" Property Entry if we're not looking at the same control.
                        // If we don't do this, Two controls that have conditionals on the same named property will have
                        // their conditionals incorrectly merged.
                        if (String.Compare(previousControlName, entry.ControlID, StringComparison.Ordinal) != 0)
                        {
                            newControl = true;
                        }
                        else
                        {
                            newControl = false;
                        }

                        previousControlName = entry.ControlID;

                        if (newControl)
                        {
                            control = container.FindControl(entry.ControlID);

                            if (control == null || !entry.ControlType.IsInstanceOfType(control))
                            {
                                Debug.Assert(false, "BoundPropertyEntry is of wrong control type or couldn't be found.  Expected " + entry.ControlType.Name);
                                continue;
                            }
                        }

                        string propertyName;
                        // map the property in case it's a complex property
                        object targetObject = PropertyMapper.LocatePropertyObject(control, entry.Name, out propertyName, InDesigner);

                        // FastPropertyAccessor uses ReflectEmit for lightning speed
                        table[entry.FieldName] = FastPropertyAccessor.GetProperty(targetObject, propertyName, InDesigner);
                    }

                    ExtractTemplateValuesRecursive(subBuilderControlBuilder.SubBuilders, table, container);
                }
            }
        }
예제 #2
0
        /*
         * Set all the properties we have on the passed in object
         * This is not called when generating code for compiling... it is
         * used in design-mode, and at runtime when the user calls Page.ParseControl
         */
        internal void SetProperties(object obj)
        {
            Debug.Assert(_fInDesigner, "Expected to be running in design mode.");

            object[] parameters = new object[1];

            IAttributeAccessor    attributeAccessor = null;
            DataBindingCollection dataBindings      = null;

            if (_fDataBound && (_entries.Count != 0))
            {
                Debug.Assert(obj is Control, "SetProperties on databindings PropertySetter should only be called for controls.");
                dataBindings = ((IDataBindingsAccessor)obj).DataBindings;
            }

            // Get the supported attribute interfaces
            if (_fSupportsAttributes)
            {
                attributeAccessor = (IAttributeAccessor)obj;
            }

            IEnumerator en = _entries.GetEnumerator();

            while (en.MoveNext())
            {
                PropertySetterEntry entry = (PropertySetterEntry)en.Current;

                if (entry._propType == null)
                {
                    if (entry._fItemProp)
                    {
                        try {
                            object objValue = entry._builder.BuildObject();
                            parameters[0] = objValue;

                            MethodInfo methodInfo = _objType.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static,
                                                                       null /*binder*/, new Type[] { objValue.GetType() }, null /*modifiers*/);
                            Util.InvokeMethod(methodInfo, obj, parameters);
                        }
                        catch (Exception) {
                            throw new HttpException(
                                      HttpRuntime.FormatResourceString(SR.Cannot_add_value_not_collection, entry._value));
                        }
                    }
                    else
                    {
                        // If there is no property, use SetAttribute
                        if (attributeAccessor != null)
                        {
                            attributeAccessor.SetAttribute(entry._name, entry._value);
                        }
                    }
                }
                else
                {
                    // Use the propinfo to set the prop
                    // Use either _propValue or _builder, whichever is set
                    if (entry._propValue != null)
                    {
                        try {
                            PropertyMapper.SetMappedPropertyValue(obj, entry._name, entry._propValue);
                        }
                        catch (Exception e) {
                            throw new HttpException(
                                      HttpRuntime.FormatResourceString(SR.Cannot_set_property,
                                                                       entry._value, entry._name), e);
                        }
                    }
                    else if (entry._builder != null)
                    {
                        if (entry._fReadOnlyProp)
                        {
                            // a complex property is allowed to be readonly
                            try {
                                object objValue;

                                // Get the property since its readonly
                                MethodInfo methodInfo = entry._propInfo.GetGetMethod();
                                objValue = Util.InvokeMethod(methodInfo, obj, null);

                                // now we need to initialize this property
                                entry._builder.InitObject(objValue);
                            }
                            catch (Exception e) {
                                throw new HttpException(
                                          HttpRuntime.FormatResourceString(SR.Cannot_init, entry._name), e);
                            }
                        }
                        else
                        {
                            try {
                                object objValue = entry._builder.BuildObject();
                                parameters[0] = objValue;

                                // Set the property
                                MethodInfo methodInfo = entry._propInfo.GetSetMethod();
                                Util.InvokeMethod(methodInfo, obj, parameters);
                            }
                            catch (Exception e) {
                                throw new HttpException(
                                          HttpRuntime.FormatResourceString(SR.Cannot_set_property,
                                                                           entry._value, entry._name), e);
                            }
                        }
                    }
                    else if (dataBindings != null)
                    {
                        DataBinding binding = new DataBinding(entry._name, entry._propType, entry._value.Trim());

                        dataBindings.Add(binding);
                    }
                    else
                    {
                        Debug.Assert(false, "'" + entry._value + "' failed to be set on property '" + entry._name + "'.");
                    }
                }
            }
        }
예제 #3
0
        private void AddPropertyInternal(string name, string value,
                                         ControlBuilder builder, bool fItemProp)
        {
            PropertySetterEntry entry = new PropertySetterEntry();
            bool   fTemplate          = false;
            string nameForCodeGen     = null;

            entry._value     = value;
            entry._builder   = builder;
            entry._fItemProp = fItemProp;

            MemberInfo   memberInfo = null;
            PropertyInfo propInfo   = null;
            FieldInfo    fieldInfo  = null;

            // Is the property a template?
            if (builder != null && builder is TemplateBuilder)
            {
                fTemplate = true;
            }

            if (_objType != null && name != null)     // attempt to locate a public property or field
                                                      // of given name on this type of object
            {
                memberInfo = PropertyMapper.GetMemberInfo(_objType, name, out nameForCodeGen);
            }

            if (memberInfo != null)             // memberInfo may be a PropertyInfo or FieldInfo
            {
                if (memberInfo is PropertyInfo) // public property
                {
                    propInfo        = (PropertyInfo)memberInfo;
                    entry._propType = propInfo.PropertyType;

                    if (propInfo.GetSetMethod() == null)              // property is readonly
                    {
                        if (builder == null && !_fSupportsAttributes) // only complex property is allowed to be readonly
                        {
                            throw new HttpException(
                                      HttpRuntime.FormatResourceString(SR.Property_readonly, name));
                        }

                        if (builder != null)     // complex property is allowed to be readonly
                                                 // set a flag to note that property is readonly
                        {
                            entry._fReadOnlyProp = true;
                        }
                        else if (_fSupportsAttributes)     // allow attribute to be set via SetAttribute
                        {
                            entry._propType = null;
                            entry._name     = name;
                        }
                    }
                }
                else     // public field
                {
                    fieldInfo       = (FieldInfo)memberInfo;
                    entry._propType = fieldInfo.FieldType;
                }

                if (entry._propType != null)
                {
                    entry._propInfo  = propInfo;
                    entry._fieldInfo = fieldInfo;
                    entry._name      = nameForCodeGen;

                    // If it's a databound prop, we don't want to mess with the value,
                    // since it's a piece of code.
                    if (!_fDataBound)
                    {
                        // check that the property is persistable, i.e., it makes sense to have it in
                        // the aspx template
                        if (_checkPersistable && nameForCodeGen != null)
                        {
                            PropertyDescriptor propDesc = _descriptors[nameForCodeGen];
                            if (propDesc != null)
                            {
                                if (propDesc.Attributes.Contains(DesignerSerializationVisibilityAttribute.Hidden))
                                {
                                    throw new HttpException(HttpRuntime.FormatResourceString(SR.Property_Not_Persistable, name));
                                }
                            }
                        }
                        else
                        {
                            if (_isHtmlControl)
                            {
                                PropertyDescriptor propDesc = _descriptors[nameForCodeGen];
                                if (propDesc != null)
                                {
                                    if (propDesc.Attributes.Contains(HtmlControlPersistableAttribute.No))
                                    {
                                        throw new HttpException(HttpRuntime.FormatResourceString(SR.Property_Not_Persistable, name));
                                    }
                                }
                            }
                        }

                        entry._propValue = PropertyConverter.ObjectFromString(entry._propType,
                                                                              memberInfo, entry._value);

                        // use actual property value to get the proper case-sensitive name for enum types
                        if (entry._propType.IsEnum)
                        {
                            if (entry._propValue == null)
                            {
                                throw new HttpException(
                                          HttpRuntime.FormatResourceString(SR.Invalid_enum_value,
                                                                           entry._value, name, entry._propType.FullName));
                            }

                            entry._value = Enum.Format(entry._propType, entry._propValue, "G");
                        }
                        else if (entry._propType == typeof(Boolean))
                        {
                            // get the proper case-sensitive value for boolean
                            if (entry._value != null && entry._value.Length > 0)
                            {
                                entry._value = entry._value.ToLower(CultureInfo.InvariantCulture);
                            }
                            else
                            {
                                entry._propValue = true;
                            }
                        }

                        if (fTemplate)
                        {
                            // Check if the property has a TemplateContainerAttribute, and if
                            // it does, get the type out of it.
                            TemplateContainerAttribute templateAttrib =
                                (TemplateContainerAttribute)Attribute.GetCustomAttribute(propInfo, typeof(TemplateContainerAttribute), false);
                            if (templateAttrib != null)
                            {
                                if (!typeof(INamingContainer).IsAssignableFrom(templateAttrib.ContainerType))
                                {
                                    throw new HttpException(HttpRuntime.FormatResourceString(
                                                                SR.Invalid_template_container, name, templateAttrib.ContainerType.FullName));
                                }
                                builder._ctrlType = templateAttrib.ContainerType;
                            }
                        }
                    }
                }
            }
            else if (fItemProp)
            {
            }
            else     // could not locate a public property or field

            // determine if there is an event of this name.
            // do not look for events when running in designer
            {
                if (!_fInDesigner &&
                    _objType != null &&
                    name.Length >= 2 && string.Compare(name.Substring(0, 2), "on", true, CultureInfo.InvariantCulture) == 0)
                {
                    string eventName = name.Substring(2);
                    if (_eventDescs == null)
                    {
                        _eventDescs = TypeDescriptor.GetEvents(_objType);
                    }
                    EventDescriptor eventFound = _eventDescs.Find(eventName, true);
                    if (eventFound != null)     // an Add method has been located

                    {
                        PropertySetterEventEntry eventEntry = new PropertySetterEventEntry();
                        eventEntry._eventName   = eventFound.Name;
                        eventEntry._handlerType = eventFound.EventType;

                        if (value == null || value.Length == 0)
                        {
                            throw new HttpException(
                                      HttpRuntime.FormatResourceString(SR.Event_handler_cant_be_empty, name));
                        }

                        eventEntry._handlerMethodName = value;

                        if (_events == null)
                        {
                            _events = new ArrayList(3);
                        }

                        // add to the list of events
                        _events.Add(eventEntry);

                        return;
                    }
                }

                // If attributes are not supported, or the property is a template or a
                // complex property (which cannot be set through SetAttribute), fail.
                if (!_fInDesigner && (!_fSupportsAttributes || builder != null))
                {
                    if (_objType != null)
                    {
                        throw new HttpException(
                                  HttpRuntime.FormatResourceString(SR.Type_doesnt_have_property, _objType.FullName, name));
                    }

                    if (String.Compare(name, "name", true, CultureInfo.InvariantCulture) != 0)
                    {
                        throw new HttpException(HttpRuntime.FormatResourceString(SR.Templates_cannot_have_properties));
                    }
                    else
                    {
                        return;
                    }
                }

                // use the original property name for generic SetAttribute
                entry._name = name;
            }

            if (_entries == null)
            {
                _entries = new ArrayList(3);
            }

            // add entry to the list
            _entries.Add(entry);
        }
예제 #4
0
        private void ApplyComplexProperties(Control control)
        {
            ICollection entries = GetFilteredPropertyEntrySet(_skinBuilder.ComplexPropertyEntries);

            foreach (ComplexPropertyEntry entry in entries)
            {
                ControlBuilder builder = entry.Builder;
                if (builder != null)
                {
                    string propertyName = entry.Name;
                    if (entry.ReadOnly)
                    {
                        object objectValue = FastPropertyAccessor.GetProperty(control, propertyName, InDesigner);
                        if (objectValue == null)
                        {
                            continue;
                        }

                        entry.Builder.SetServiceProvider(ServiceProvider);
                        try {
                            entry.Builder.InitObject(objectValue);
                        }
                        finally {
                            entry.Builder.SetServiceProvider(null);
                        }
                    }
                    else
                    {
                        object childObj;
                        string actualPropName;
                        object value = entry.Builder.BuildObject(true);

                        // Make the UrlProperty based on theme path for control themes(Must be a string)
                        PropertyDescriptor desc = PropertyMapper.GetMappedPropertyDescriptor(control, PropertyMapper.MapNameToPropertyName(propertyName), out childObj, out actualPropName, InDesigner);
                        if (desc != null)
                        {
                            string str = value as string;
                            if (value != null && desc.Attributes[typeof(UrlPropertyAttribute)] != null &&
                                UrlPath.IsRelativeUrl(str))
                            {
                                value = _themePath + str;
                            }
                        }

                        FastPropertyAccessor.SetProperty(childObj, propertyName, value, InDesigner);
                    }
                }
            }
        }