программно изменить значение атрибута
От: Аноним  
Дата: 01.06.11 13:22
Оценка:
public class A
{
  [DisplayName(Name = "aaaaa")]
  public object Value {get; set;}
}


Как программно изменить значение атрибута?

Получится ли для этих целей использовать PropertyDescriptor или ICustomTypeDescriptor, что бы при запросе атрибутов — возвращались программно сгенерированные?

Что-то типа:

public AttributeCollection GetAttributes()
{
  return new AttributeCollection(new Attribute[] { x, y });
}
Re: программно изменить значение атрибута
От: _FRED_ Черногория
Дата: 01.06.11 13:46
Оценка:
Здравствуйте, Аноним, Вы писали:

А>public class A
А>{
А>  [DisplayName(Name = "aaaaa")]
А>  public object Value {get; set;}
А>}

А>Как программно изменить значение атрибута?

Атрибут — это метаданные. Сами метаданные изменить в рантайме нельзя.

Но некоторые методы доступа к метаданным позволяют вмешаться в процесс получения метаданных и управлять им.

А>Получится ли для этих целей использовать PropertyDescriptor или ICustomTypeDescriptor, что бы при запросе атрибутов — возвращались программно сгенерированные?


Ключёвое тут — это как происходит "запросе атрибутов". В дотнете есть несколько способов для этого: CustomAttributeData::GetCustomAttributes, MemberInfo::GetCustomAttributes и TypeDescriptor::GetAttributes/MemberDescriptor::Attributes. Последний способ расширяем, но и ограничен — атрибутами уровня типа/свойства/события.

Если вы "переедете" этот способ и будете возвращать что-то своё, то те, кто получают доступ к атрибутам другими путями, ваших изменений "не увидят".

Кто и каким образом будет запрашивать интересующие вас атрибуты?
Help will always be given at Hogwarts to those who ask for it.
Re: программно изменить значение атрибута
От: hardcase Пират http://nemerle.org
Дата: 01.06.11 13:47
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Как программно изменить значение атрибута?


Никак. Значения полей (и свойств) атрибутов записываются в метаданные сборки.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: программно изменить значение атрибута
От: _FRED_ Черногория
Дата: 01.06.11 13:54
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Ключёвое тут — это как происходит "запросе атрибутов". В дотнете есть несколько способов для этого: CustomAttributeData::GetCustomAttributes, MemberInfo::GetCustomAttributes и TypeDescriptor::GetAttributes/MemberDescriptor::Attributes. Последний способ расширяем, но и ограничен — атрибутами уровня типа/свойства/события.


_FR>Если вы "переедете" этот способ и будете возвращать что-то своё, то те, кто получают доступ к атрибутам другими путями, ваших изменений "не увидят".


Ещё и ещё один путь — написать свой собственный способ получения атрибутов (на основе одного из вышеперечисленных). но никто кроме вас им пользоваться не сможет.
Help will always be given at Hogwarts to those who ask for it.
Re[2]: программно изменить значение атрибута
От: Аноним  
Дата: 02.06.11 10:14
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Ключёвое тут — это как происходит "запросе атрибутов". В дотнете есть несколько способов для этого: CustomAttributeData::GetCustomAttributes, MemberInfo::GetCustomAttributes и TypeDescriptor::GetAttributes/MemberDescriptor::Attributes. Последний способ расширяем, но и ограничен — атрибутами уровня типа/свойства/события.


Это я хотел для APS.NET MVC @Html.TextBoxFor(...)

Судя по исходникам там метаданные берутся с помощью TypeDescriptor.

Т.е. если я сделаю свой класс MyValue, унаследованный от ICustomTypeDescriptor, то можно будет динамически предоставлять атрибуты?


[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
public static ModelMetadata FromLambdaExpression<TParameter, TValue>(Expression<Func<TParameter, TValue>> expression,
                                                                     ViewDataDictionary<TParameter> viewData) {
...

    switch (expression.Body.NodeType) {

        // Property/field access is always legal
        case ExpressionType.MemberAccess:
            MemberExpression memberExpression = (MemberExpression)expression.Body;
            propertyName = memberExpression.Member is PropertyInfo ? memberExpression.Member.Name : null;
            containerType = memberExpression.Expression.Type;
            legalExpression = true;
            break;
    }
...
}
...

ICustomTypeDescriptor typeDescriptor = GetTypeDescriptor(containerType);
PropertyDescriptor property = typeDescriptor.GetProperties().Find(propertyName, true);


...
IEnumerable<Attribute> attributes = GetTypeDescriptor(modelType).GetAttributes().Cast<Attribute>();
...


...
Re[3]: программно изменить значение атрибута
От: _FRED_ Черногория
Дата: 02.06.11 11:16
Оценка:
Здравствуйте, Аноним, Вы писали:

_FR>>Ключёвое тут — это как происходит "запросе атрибутов". В дотнете есть несколько способов для этого: CustomAttributeData::GetCustomAttributes, MemberInfo::GetCustomAttributes и TypeDescriptor::GetAttributes/MemberDescriptor::Attributes. Последний способ расширяем, но и ограничен — атрибутами уровня типа/свойства/события.


А>Это я хотел для APS.NET MVC @Html.TextBoxFor(...)

А>Судя по исходникам там метаданные берутся с помощью TypeDescriptor.
А>Т.е. если я сделаю свой класс MyValue, унаследованный от ICustomTypeDescriptor, то можно будет динамически предоставлять атрибуты?

Да, можно. Отчасти, оно для этого (расширения с помощью рантайм-подстановки атрибутов) и предназначено.

О том, как именно лучше расширять — решайте сами. Тут опять же есть нескольку путей. ICustomTypeDescriptor — если сам экземпляр определяет, что у него есть. ICustomTypeProvider — если нужную информацию можно (или нужно) предоставить пользуясь статической информацией о типе.
Help will always be given at Hogwarts to those who ask for it.
Re[4]: программно изменить значение атрибута
От: Аноним  
Дата: 03.06.11 07:04
Оценка:
Здравствуйте, _FRED_, Вы писали:

Сделал класс, реализующий ICustomTypeDescriptor, но его метод GetProperties не вызывается при @Html.TextBoxFor(


public class MyClass : ICustomTypeDescriptor
{
        public object Value;

        public PropertyDescriptorCollection GetProperties()
        {
            List<PropertyDescriptor> pdArray = new List<PropertyDescriptor>();

            foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(GetType()))
            {
                if (pd.Name == "Value")
                {
                    pdArray.Add(new MyPropertyDescriptor(1, true, "ZZZZ")); // Value = 1, Required = true, Name = "ZZZ" и создаёт атрибуты RequiredAttrubute и DisplayAttribute
                }
            }

            PropertyDescriptorCollection pdc = new PropertyDescriptorCollection(pdArray.ToArray());

            return pdc;
        }
}

...

MyClass myObject;

@Html.TextBoxFor(m => myObject.Value)
Re[5]: программно изменить значение атрибута
От: _FRED_ Черногория
Дата: 03.06.11 07:19
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Сделал класс, реализующий ICustomTypeDescriptor, но его метод GetProperties не вызывается при @Html.TextBoxFor(


Что такое @Html.TextBoxFor и как и для чего оно работает я, к сожалению, не знаю.
Help will always be given at Hogwarts to those who ask for it.
Re[6]: программно изменить значение атрибута
От: Аноним  
Дата: 03.06.11 07:52
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, Аноним, Вы писали:


А>>Сделал класс, реализующий ICustomTypeDescriptor, но его метод GetProperties не вызывается при @Html.TextBoxFor(


_FR>Что такое @Html.TextBoxFor и как и для чего оно работает я, к сожалению, не знаю.


HTM-helper из ASP.MVC 3

в нём есть такой код:

[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
public static ModelMetadata FromLambdaExpression<TParameter, TValue>(Expression<Func<TParameter, TValue>> expression,
                                                                     ViewDataDictionary<TParameter> viewData) {
...

    switch (expression.Body.NodeType) {

        // Property/field access is always legal
        case ExpressionType.MemberAccess:
            MemberExpression memberExpression = (MemberExpression)expression.Body;
            propertyName = memberExpression.Member is PropertyInfo ? memberExpression.Member.Name : null;
            containerType = memberExpression.Expression.Type;
            legalExpression = true;
            break;
    }
...
}
...

ICustomTypeDescriptor typeDescriptor = GetTypeDescriptor(containerType);
PropertyDescriptor property = typeDescriptor.GetProperties().Find(propertyName, true);


...
IEnumerable<Attribute> attributes = GetTypeDescriptor(modelType).GetAttributes().Cast<Attribute>();
...


...
Re[7]: программно изменить значение атрибута
От: _FRED_ Черногория
Дата: 03.06.11 07:58
Оценка:
Здравствуйте, Аноним, Вы писали:

А>>>Сделал класс, реализующий ICustomTypeDescriptor, но его метод GetProperties не вызывается при @Html.TextBoxFor(

_FR>>Что такое @Html.TextBoxFor и как и для чего оно работает я, к сожалению, не знаю.
А>HTM-helper из ASP.MVC 3

А>в нём есть такой код:


Ага, теперь ясно к чему был этот код выше. Видите:
А>IEnumerable<Attribute> attributes = GetTypeDescriptor(modelType).GetAttributes().Cast<Attribute>();


Что такое modelType и откуда берётся? Какое отношение имеет к выражению "m => myObject.Value"? Это тип myObject? Тип Value? Что-то ещё?
Help will always be given at Hogwarts to those who ask for it.
Re[8]: программно изменить значение атрибута
От: Аноним  
Дата: 03.06.11 09:04
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, Аноним, Вы писали:


А>>>>Сделал класс, реализующий ICustomTypeDescriptor, но его метод GetProperties не вызывается при @Html.TextBoxFor(

_FR>>>Что такое @Html.TextBoxFor и как и для чего оно работает я, к сожалению, не знаю.
А>>HTM-helper из ASP.MVC 3

А>>в нём есть такой код:


_FR>Ага, теперь ясно к чему был этот код выше. Видите:

_FR>
А>>IEnumerable<Attribute> attributes = GetTypeDescriptor(modelType).GetAttributes().Cast<Attribute>();
_FR>


_FR>Что такое modelType и откуда берётся? Какое отношение имеет к выражению "m => myObject.Value"? Это тип myObject? Тип Value? Что-то ещё?


[c#]
public override ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType) {
if (modelType == null) {
throw new ArgumentNullException("modelType");
}

IEnumerable<Attribute> attributes = GetTypeDescriptor(modelType).GetAttributes().Cast<Attribute>();
ModelMetadata result = CreateMetadata(attributes, null /* containerType */, modelAccessor, modelType, null /* propertyName */);
ApplyMetadataAwareAttributes(attributes, result);
return result;
}

// или
public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName) {
if (containerType == null) {
throw new ArgumentNullException("containerType");
}
if (String.IsNullOrEmpty(propertyName)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "propertyName");
}

ICustomTypeDescriptor typeDescriptor = GetTypeDescriptor(containerType);
PropertyDescriptor property = typeDescriptor.GetProperties().Find(propertyName, true);
if (property == null) {
throw new ArgumentException(
String.Format(
CultureInfo.CurrentCulture,
MvcResources.Common_PropertyNotFound,
containerType.FullName, propertyName));
}

return GetMetadataForProperty(modelAccessor, containerType, property);
}

protected virtual ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, PropertyDescriptor propertyDescriptor) {
IEnumerable<Attribute> attributes = FilterAttributes(containerType, propertyDescriptor, propertyDescriptor.Attributes.Cast<Attribute>());
ModelMetadata result = CreateMetadata(attributes, containerType, modelAccessor, propertyDescriptor.PropertyType, propertyDescriptor.Name);
ApplyMetadataAwareAttributes(attributes, result);
return result;
}

[c#]

Код из AssociatedMetadataProvider из исходников ASP.NET MVC

Может я ещё не в том месте смотрю...
Re[9]: программно изменить значение атрибута
От: Аноним  
Дата: 03.06.11 09:10
Оценка:
А>Здравствуйте, _FRED_, Вы писали:

        public override ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType) {
            if (modelType == null) {
                throw new ArgumentNullException("modelType");
            }

            IEnumerable<Attribute> attributes = GetTypeDescriptor(modelType).GetAttributes().Cast<Attribute>();
            ModelMetadata result = CreateMetadata(attributes, null /* containerType */, modelAccessor, modelType, null /* propertyName */);
            ApplyMetadataAwareAttributes(attributes, result);
            return result;
        }

// или

        public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName) {
            if (containerType == null) {
                throw new ArgumentNullException("containerType");
            }
            if (String.IsNullOrEmpty(propertyName)) {
                throw new ArgumentException(MvcResources.Common_NullOrEmpty, "propertyName");
            }

            ICustomTypeDescriptor typeDescriptor = GetTypeDescriptor(containerType);
            PropertyDescriptor property = typeDescriptor.GetProperties().Find(propertyName, true);
            if (property == null) {
                throw new ArgumentException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        MvcResources.Common_PropertyNotFound,
                        containerType.FullName, propertyName));
            }

            return GetMetadataForProperty(modelAccessor, containerType, property);
        }

        protected virtual ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, PropertyDescriptor propertyDescriptor)         {
            IEnumerable<Attribute> attributes = FilterAttributes(containerType, propertyDescriptor, propertyDescriptor.Attributes.Cast<Attribute>());
            ModelMetadata result = CreateMetadata(attributes, containerType, modelAccessor, propertyDescriptor.PropertyType, propertyDescriptor.Name);
            ApplyMetadataAwareAttributes(attributes, result);
            return result;
        }
Re[9]: программно изменить значение атрибута
От: _FRED_ Черногория
Дата: 03.06.11 09:37
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Может я ещё не в том месте смотрю...


Попробуйте поотлаживаться по исходникам.
Help will always be given at Hogwarts to those who ask for it.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.