ViewState как атрибут

Программы Lisp не являются плоскими файлами. Они - сериализация структур данных. Этот код поскольку данные является старой идеей, и на самом деле одной из самой большой идеи в информатике.

16
задан BBorg 4 November 2009 в 14:10
поделиться

4 ответа

Вот так:

public class BasePage: Page {

    protected override Object SaveViewState() {

        object baseState                      = base.SaveViewState();            
        IDictionary<string, object> pageState = new Dictionary<string, object>();
        pageState.Add("base", baseState);

        // Use reflection to iterate attributed properties, add 
        // each to pageState with the property name as the key

        return pageState;
    }

    protected override void LoadViewState(Object savedState) {

        if (savedState != null) {

            var pageState = (IDictionary<string, object>)savedState;

            if (pageState.Contains("base")) {
                base.LoadViewState(pageState["base"]);
            }

            // Iterate attributed properties. If pageState contains an
            // item with the appropriate key, set the property value.

        }
    }
}

Страницы, унаследованные от этого класса, могут использовать предложенный вами синтаксис на основе атрибутов.

5
ответ дан 30 November 2019 в 23:21
поделиться

This functionality is built into NHibernate Burrow. If you don't happen to use NHibernate in your application, the source code for NHibernate Burrow is available here. Feel free to dig in, see how they did it, and rip out any parts that our useful to you (as long as you comply with the LGPL license).

The most relevant code seems to be in StatefulFieldProcessor.cs lines 51 - 72.

        /// <summary>
    /// Get the FieldInfo - Attribute pairs that have the customer attribute of type <typeparamref name="AT"/> 
    /// </summary>
    /// <typeparam name="AT"></typeparam>
    /// <returns></returns>
    protected IDictionary<FieldInfo, AT> GetFieldInfo<AT>() where AT : Attribute {
        IDictionary<FieldInfo, AT> retVal = new Dictionary<FieldInfo, AT>();
        foreach (FieldInfo fi in GetFields())
            foreach (AT a in Attribute.GetCustomAttributes(fi, typeof (AT)))
                retVal.Add(fi, a);
        return retVal;
    }

    protected IDictionary<FieldInfo, StatefulField> GetStatefulFields() {
        IDictionary<FieldInfo, StatefulField> retVal;
        Type controlType = Control.GetType();
        if (controlType.Assembly == webAssembly)
            return null;
        if (!fieldInfoCache.TryGetValue(controlType, out retVal))
            fieldInfoCache[controlType] = retVal = GetFieldInfo<StatefulField>();
        return retVal;
    }
0
ответ дан 30 November 2019 в 23:21
поделиться

Ну, это то, что я получил до сих пор, TY Джефф за то, что указал мне в правильном направлении:

TestPage:

public partial class Pages_Test : BasePage    {
    [ViewState]
    public String Name { get; set; }

BasePage:

    #region Support ViewState Attribute

    BindingFlags _flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;

    protected override Object SaveViewState()
    {
        object _baseState = base.SaveViewState();
        IDictionary<string, object> _pageState = new Dictionary<string, object> { { "base", _baseState } };

        //Use reflection to get properties marked for viewstate

        foreach (PropertyInfo _property in GetType().GetProperties(_flags))
        {
            if (_property.HasAttribute<ViewState>())
            {
                object _value = _property.GetValue(this, _flags , null, null, null);
                _pageState.Add(new KeyValuePair<string, object>(_property.Name, _value));
            }
        }
        return _pageState;
    }

    protected override void LoadViewState(Object savedState)
    {
        if (savedState != null)
        {
            var _pageState = (IDictionary<string, object>)savedState;

            if (_pageState.ContainsKey("base"))
            {
                base.LoadViewState(_pageState["base"]);
            }
            //use reflection to set properties 
            foreach (PropertyInfo _property in GetType().GetProperties(_flags ))
            {
                if (_property.HasAttribute<ViewState>() && _pageState.ContainsKey(_property.Name))
                {
                    object _value = _pageState[_property.Name];
                    _property.SetValue(this, _value, _flags , null, null, null);
                }
            }
        }
    }
    #endregion

Атрибут:

/// <summary>
/// This attribute is used by the BasePage to identify properties that should be persisted to ViewState
/// Note: Private properties are not supported
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class ViewState : Attribute
{
    //Marker
}

Помощники:

public static class PropertyExtension
{
    public static Boolean HasAttribute<T>(this PropertyInfo property)
    {
        object[] attrs = property.GetCustomAttributes(typeof(T), false);
        return attrs != null && attrs.Length == 1;
    }

}

РЕДАКТИРОВАТЬ

У Яна есть веское мнение о производительности, я провел некоторое профилирование и получил следующие результаты:

                 Without Attribute    With Attribute   Increase   Slower %
One Property     
       First Load        0,004897899     0,010734255    0,005836356    219
       Save, postback    0,002353861     0,010478008    0,008124147    445
       Load, Postback    0,001488807     0,00627482     0,004786013    421
   10 properties  
       First Load        0,006184096     0,015288675    0,009104579    247
       Save, postback    0,004061759     0,015052262    0,010990503    371
       Load, Postback    0,0015708       0,005833074    0,004262274    371

              % increase
Avg Page. 0,902215714567075 0,00648

На пустой странице рост значительный, но на средней странице с загрузкой в ​​1 с это увеличение составляет 0,01%.


Обновление : Использование PostSharp, PostSharp4ViewState

Шаг 1: Убедитесь, что ваш веб-сайт предварительно скомпилирован

Шаг 2: Установите PostSharp и PostSharp4ViewState

Шаг 3: Ссылка на PostSharp.Public и PostSharp4ViewState

Шаг 4: Следующий код теперь действителен.

      [Persist(Mode=PersistMode.ViewState)]
      private string _name;
   public String Name { 
    get { return _name; }
    set { _name = value; }
   }
2
ответ дан 30 November 2019 в 23:21
поделиться

Решение BBorg на самом деле невероятно медленное из-за интенсивного использования отражения.

Используя PostSharp.Laos, позволяя вашему атрибуту наследовать от OnMethodBoundaryAspect , вы можете легко переопределить public override void OnInvocation (MethodInvocationEventArgs eventArgs) и творить там всю магию. Это будет намного быстрее. Посмотрите, например, пример CacheAttribute на домашней странице PostSharp.

Если вам действительно нужна голая скорость, вы можете написать плагин PostSharp, который вплетает MSIL (методы GetFromViewState, SetInViewState или что-то еще) в ваши свойства, чтобы даже не будет потери производительности.

1
ответ дан 30 November 2019 в 23:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: