Проверьте, имеет ли свойство пользовательский атрибут для системных типов C # [дубликат]

Давайте сначала поймем, что такое позиционные аргументы и аргументы ключевых слов. Ниже приведен пример определения функции с помощью аргументов Positional.

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(1,2,3)
#output:
1
2
3

Итак, это определение функции с позиционными аргументами. Вы также можете вызвать его с помощью ключевых слов / названных аргументов:

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(a=1,b=2,c=3)
#output:
1
2
3

Теперь давайте рассмотрим пример определения функции с аргументами ключевого слова:

def test(a=0,b=0,c=0):
     print(a)
     print(b)
     print(c)
     print('-------------------------')

test(a=1,b=2,c=3)
#output :
1
2
3
-------------------------

Вы можете вызвать эту функцию с позиционными аргументами:

def test(a=0,b=0,c=0):
    print(a)
    print(b)
    print(c)
    print('-------------------------')

test(1,2,3)
# output :
1
2
3
---------------------------------

Итак, теперь мы знаем определения функций с позиционными и ключевыми аргументами.

Теперь давайте изучим оператор '*' и '** '.

Обратите внимание, что эти операторы могут использоваться в двух областях:

a) вызов функции

b) определение функции

Использование оператора «*» и оператора «**» в вызове функции.

Обратимся к примеру, а затем обсудим его.

def sum(a,b):  #receive args from function calls as sum(1,2) or sum(a=1,b=2)
    print(a+b)

my_tuple = (1,2)
my_list = [1,2]
my_dict = {'a':1,'b':2}

# Let us unpack data structure of list or tuple or dict into arguments with help of '*' operator
sum(*my_tuple)   # becomes same as sum(1,2) after unpacking my_tuple with '*'
sum(*my_list)    # becomes same as sum(1,2) after unpacking my_list with  '*'
sum(**my_dict)   # becomes same as sum(a=1,b=2) after unpacking by '**' 

# output is 3 in all three calls to sum function.

Итак, помните

, когда оператор '*' или '**' используемый в вызове функции -

'*', распаковывает структуру данных, такую ​​как список или кортеж, в аргументы, необходимые для определения функции.

Оператор `** 'распаковывает словарь в аргументы необходимых для определения функции.

Теперь давайте изучим использование оператора «*» в определении функции. Пример:

def sum(*args): #pack the received positional args into data structure of tuple. after applying '*' - def sum((1,2,3,4))
    sum = 0
    for a in args:
        sum+=a
    print(sum)

sum(1,2,3,4)  #positional args sent to function sum
#output:
10

В определении функции оператор «*» упаковывает полученные аргументы в кортеж.

Теперь давайте посмотрим пример «**», используемый в определении функции :

def sum(**args): #pack keyword args into datastructure of dict after applying '**' - def sum({a:1,b:2,c:3,d:4})
    sum=0
    for k,v in args.items():
        sum+=v
    print(sum)

sum(a=1,b=2,c=3,d=4) #positional args sent to function sum

В определении функции Оператор '**' упаковывает полученные аргументы в словарь.

Итак, помните:

В вызове функции '*' распаковывает структуру данных кортежа или списка в позиционные или ключевые аргументы, которые должны быть получены определением функции.

В вызове функции '**' распаковывает структуру данных словаря в позиционные или ключевые аргументы полученное определением функции.

В определении функции «*» помещает позиционные аргументы в кортеж.

В определении функции «**» упаковывает аргументы ключевого слова в словарь.

124
задан Otávio Décio 12 January 2010 в 18:44
поделиться

8 ответов

Не существует быстрого способа получения атрибутов. Но код должен выглядеть так (кредит Aaronaught ):

var t = typeof(YourClass);
var pi = t.GetProperty("Id");
var hasIsIdentity = Attribute.IsDefined(pi, typeof(IsIdentity));

Если вам нужно получить свойства атрибута, то

var t = typeof(YourClass);
var pi = t.GetProperty("Id");
var attr = (IsIdentity[])pi.GetCustomAttributes(typeof(IsIdentity), false);
if (attr.Length > 0) {
    // Use attr[0], you'll need foreach on attr if MultiUse is true
}
225
ответ дан Rob 27 August 2018 в 04:42
поделиться
  • 1
    Если вам нужно только проверить наличие атрибута и не извлекать из него какую-либо информацию, использование Attribute.IsDefined приведет к удалению одной строки кода и уродливых массивов / кастингов. – Aaronaught 12 January 2010 в 19:42
  • 2
    Что-то, с чем я просто столкнулся с этим, - это некоторые атрибуты, относящиеся к их имени атрибута. Например, "NotMapped" в System.ComponentModel.DataAnnotations.Schema используется как [NotMapped] в классе, но для его обнаружения вы должны использовать Attribute.IsDefined(pi, typeof(NotMappedAttribute)) – Qjimbo 13 July 2018 в 21:41

Если вы используете .NET 3.5, вы можете попробовать с помощью деревьев выражений. Это безопаснее, чем отражение:

class CustomAttribute : Attribute { }

class Program
{
    [Custom]
    public int Id { get; set; }

    static void Main()
    {
        Expression<Func<Program, int>> expression = p => p.Id;
        var memberExpression = (MemberExpression)expression.Body;
        bool hasCustomAttribute = memberExpression
            .Member
            .GetCustomAttributes(typeof(CustomAttribute), false).Length > 0;
    }
}
41
ответ дан Darin Dimitrov 27 August 2018 в 04:42
поделиться
  • 1
    FYI был задан вопрос о вашем ответе. [Д0] stackoverflow.com/questions/4158996/… – Greg 11 November 2010 в 21:35

Вы можете использовать метод Attribute.IsDefined

https://msdn.microsoft.com/en-us/library/system.attribute.isdefined (v = vs.110). aspx

if(Attribute.IsDefined([YourProperty],typeof([YourAttribute])))
{
    //Conditional execution...
}

Вы можете указать свойство, которое вы специально ищете, или вы можете перебирать все из них с помощью отражения, например:

PropertyInfo[] props = typeof([YourClass]).GetProperties();
1
ответ дан Francis Musignac 27 August 2018 в 04:42
поделиться

Если вы пытаетесь сделать это в PCL Portable Class Library (например, я), то вот как вы можете это сделать:)

public class Foo
{
   public string A {get;set;}

   [Special]
   public string B {get;set;}   
}

var type = typeof(Foo);

var specialProperties = type.GetRuntimeProperties()
     .Where(pi => pi.PropertyType == typeof (string) 
      && pi.GetCustomAttributes<Special>(true).Any());

Затем вы можете проверить количество свойств которые имеют это особое свойство, если вам нужно.

5
ответ дан Has AlTaiar 27 August 2018 в 04:42
поделиться

Теперь это можно сделать без деревьев выражений и методов расширения безопасным типом с новой функцией C # nameof() следующим образом:

Attribute.IsDefined(typeof(YourClass).GetProperty(nameof(YourClass.Id)), typeof(IsIdentity));
0
ответ дан Jim Wolff 27 August 2018 в 04:42
поделиться

Вы можете использовать общий (общий) метод для чтения атрибута над данным MemberInfo

public static bool TryGetAttribute<T>(MemberInfo memberInfo, out T customAttribute) where T: Attribute {
                var attributes = memberInfo.GetCustomAttributes(typeof(T), false).FirstOrDefault();
                if (attributes == null) {
                    customAttribute = null;
                    return false;
                }
                customAttribute = (T)attributes;
                return true;
            }
11
ответ дан Manish Basantani 27 August 2018 в 04:42
поделиться

Это довольно старый вопрос, но я использовал

. Мой метод имеет этот параметр, но он может быть построен:

Expression<Func<TModel, TValue>> expression

Затем в методе this:

System.Linq.Expressions.MemberExpression memberExpression 
       = expression.Body as System.Linq.Expressions.MemberExpression;
Boolean hasIdentityAttr = System.Attribute
       .IsDefined(memberExpression.Member, typeof(IsIdentity));
1
ответ дан Mark Schultheiss 27 August 2018 в 04:42
поделиться

Чтобы обновить и / или улучшить ответ от @Hans Passant, я бы отделил поиск свойства в метод расширения. Это имеет дополнительное преимущество для удаления неприятной магической строки в методе GetProperty ()

public static class PropertyHelper<T>
{
    public static PropertyInfo GetProperty<TValue>(
        Expression<Func<T, TValue>> selector)
    {
        Expression body = selector;
        if (body is LambdaExpression)
        {
            body = ((LambdaExpression)body).Body;
        }
        switch (body.NodeType)
        {
            case ExpressionType.MemberAccess:
                return (PropertyInfo)((MemberExpression)body).Member;
            default:
                throw new InvalidOperationException();
        }
    }
}

Затем ваш тест сводится к двум строкам

var property = PropertyHelper<MyClass>.GetProperty(x => x.MyProperty);
Attribute.IsDefined(property, typeof(MyPropertyAttribute));
5
ответ дан Seb 27 August 2018 в 04:42
поделиться
Другие вопросы по тегам:

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