Давайте сначала поймем, что такое позиционные аргументы и аргументы ключевых слов. Ниже приведен пример определения функции с помощью аргументов 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
В определении функции Оператор '**' упаковывает полученные аргументы в словарь.
Итак, помните:
В вызове функции '*' распаковывает структуру данных кортежа или списка в позиционные или ключевые аргументы, которые должны быть получены определением функции.
В вызове функции '**' распаковывает структуру данных словаря в позиционные или ключевые аргументы полученное определением функции.
В определении функции «*» помещает позиционные аргументы в кортеж.
В определении функции «**» упаковывает аргументы ключевого слова в словарь.
Не существует быстрого способа получения атрибутов. Но код должен выглядеть так (кредит 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
}
Если вы используете .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;
}
}
Вы можете использовать метод 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();
Если вы пытаетесь сделать это в 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());
Затем вы можете проверить количество свойств которые имеют это особое свойство, если вам нужно.
Теперь это можно сделать без деревьев выражений и методов расширения безопасным типом с новой функцией C # nameof()
следующим образом:
Attribute.IsDefined(typeof(YourClass).GetProperty(nameof(YourClass.Id)), typeof(IsIdentity));
Вы можете использовать общий (общий) метод для чтения атрибута над данным 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;
}
Это довольно старый вопрос, но я использовал
. Мой метод имеет этот параметр, но он может быть построен:
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));
Чтобы обновить и / или улучшить ответ от @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));
Attribute.IsDefined
приведет к удалению одной строки кода и уродливых массивов / кастингов. – Aaronaught 12 January 2010 в 19:42[NotMapped]
в классе, но для его обнаружения вы должны использоватьAttribute.IsDefined(pi, typeof(NotMappedAttribute))
– Qjimbo 13 July 2018 в 21:41