Вместо этого..
public string Text
{
get { return ViewState["Text"] as string; }
set { ViewState["Text"] = value; }
}
Я бы хотел этого..
[ViewState]
public String Text { get; set; }
Можно ли это сделать?
Вместо этого..
public string Text
{
get { return ViewState["Text"] as string; }
set { ViewState["Text"] = value; }
}
Я бы хотел этого..
[ViewState]
public String Text { get; set; }
Можно ли это сделать?
Вот так:
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.
}
}
}
Страницы, которые наследуют от этого класса, могут использовать синтаксис, основанный на атрибутах, который вы предложили.
Хорошо, это то, что я получил до сих пор, Т.Ю. Джефф за то, что указал мне в правильном направлении:
тестовая страница:
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;
}
}
ИЗМЕНИТЬ
У Jan есть действительная точка производительности, я сделал некоторое профилирование со следующими результатами:
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; }
}
Решение BBorg на самом деле невероятно медленное из-за интенсивного использования отражения.
Используя PostSharp.Laos, допустив, что ваш атрибут наследуется от OnMethodBoundaryAspect
, вы можете легко переопределить public override void OnInvocation(MethodInvocationEventArgs eventArgs)
и сделать все волшебство там. Это будет быстрее. Проверьте, например, пример CacheAttribute
на домашней странице PostSharp.
Если вы действительно хотите голую скорость, вы можете написать плагин PostSharp, который вставляет свои свойства в MSIL (GetFromViewState, SetInViewState или что-то еще), что даже не может иметь штраф за производительность.
Эта функциональность встроена в NHibernate Burrow. Если вы не используете NHibernate в своем приложении, исходный код для NHibernate Burrow доступен здесь. Не стесняйтесь вникать, посмотреть, как они это сделали, и вырвать любые полезные для вас части (если вы выполняете лицензию LGPL).
Наиболее подходящий код, по-видимому, находится в строках StatefulFieldProcessor.cs 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;
}