自定义属性Attribute(三)

检测自定义属性的应用而不创建自定义属性的实例

   在调用GetCustomAttirbute及GetCustomAttirbutes方法时,都会调用属性类的构造器方法,同时也有可能调用property的get或set访问器。并且,首次访问一个类型会让CLR调用类型的类型构造器。而在构造器、访问器、类型构造器中,可能包含每次查找一个属性都会执行的代码,我们使用属性时并不知道这些代码,这样会允许未知的代码在AppDomain中运行,造成潜在的安全隐患。

         System.Reflection.CustomAttributeData类允许我们在查找自定义属性的同时禁止执行属性类的代码。其实现原理是 Assembly类的静态方法ReflectionOnlyLoad以一种特殊的方式加载程序集,期间会禁止CLR执行程序集中的任何代码,包括类型构造器。而CustomAttirbuteData类则对其加载的程序集进行分析。

         CustomAttributeData的GetCustomAttribute方法相当于一个Factory方法,它会返回IList<CustomAttirbuteData>集合。对于集合中的CustomAttributeData对象,可以访问其三个只读字段获取参数:

  1. Constructor 返回一个ConstructorInfo对象,表示构造函数“要”如何调用。
  2. ConstructorArguments  返回IList<CustomAttributeTypedArgument>集合,表示“要”传给构造函数的参数列表。
  3. NamedArguments 返回IList<CustomAttributeNamedArgument>集合,返回“要”设置的字段。

这里的构造函数、参数列表以及字段的设置不会实际的调用构造器和set访问器,这样才会增加安全性。

代码示例:

ContractedBlock.gif ExpandedBlockStart.gif CustomAttributeDataAdapter
 
   
[Serializable]
[DefaultMember(
" ShowAttribute " )]
[DebuggerDisplay(
" Shi " ,Name = " Jerry " ,Target = typeof (CustomAttributeDataAdapter))]
public class CustomAttributeDataAdapter
{
public CustomAttributeDataAdapter()
{ }

[Conditional(
" Debug " )]
[Conditional(
" Release " )]
public void DoSomething()
{ }

[CLSCompliant(
true )]
[STAThread]
public static void ShowAttribute()
{
ShowAttribute(
typeof (CustomAttributeDataAdapter));

MemberInfo[] members
= typeof (CustomAttributeDataAdapter).FindMembers(
MemberTypes.Constructor
| MemberTypes.Method,
BindingFlags.DeclaredOnly
| BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static,
Type.FilterName,
" * " );
foreach (MemberInfo member in members)
{
ShowAttribute(member);
}
}

private static void ShowAttribute(MemberInfo attributeTarget)
{
IList
< CustomAttributeData > attributes = CustomAttributeData.GetCustomAttributes(attributeTarget);

Console.WriteLine(
" Attributes applied to {0}:{1} " , attributeTarget.Name, (attributes.Count == 0 ? " None " : string .Empty));

foreach (CustomAttributeData attribute in attributes)
{
Type t
= attribute.Constructor.DeclaringType;
Console.WriteLine(
" {0} " , t.ToString());
Console.WriteLine(
" Constructor called={0} " , attribute.Constructor);

IList
< CustomAttributeTypedArgument > posArgs = attribute.ConstructorArguments;
Console.WriteLine(
" Positional arguments passed to constructor:{0} " , (posArgs.Count == 0 ) ? " None " : string .Empty);
foreach (CustomAttributeTypedArgument pa in posArgs)
{
Console.WriteLine(
" Type={0}, Value={1} " , pa.ArgumentType, pa.Value);
}

IList
< CustomAttributeNamedArgument > namedArgs = attribute.NamedArguments;
Console.WriteLine(
" Named arguments set after contruction:{0} " , (namedArgs.Count == 0 ? " None " : string .Empty));
foreach (CustomAttributeNamedArgument na in namedArgs)
{
Console.WriteLine(
" Name={0}, Type={1}, Value={2} " , na.MemberInfo.Name, na.TypedValue.ArgumentType, na.TypedValue.Value);
}
Console.WriteLine();
}
}

 

条件属性类

自定义属性的目的及方便之处在于其反射或者晚期绑定中的应用,但过多的向目标定义属性会造成元数据不断扩大,并会影响程序的性能。因此.Net引出了条件属性类(ConditionalAttribute)来解决此问题。

ConditionalAttribute 仅对自定义属性有效,并且根据编译时 csc /define:condtionalParam 参数来判断是否将自定义属性生成到元数据。

 

ContractedBlock.gif ExpandedBlockStart.gif ConditionalAttribute
 
   
[Conditional( " Debug " )]
internal class DebugAttribute : Attribute
{

}

[Conditional(
" Release " )]
internal class ReleaseAttribute : Attribute
{

}

[Debug]
internal class DebugApp
{
internal static void ShowAttribute()
{
// IList<CustomAttributeData> attributes = CustomAttributeData.GetCustomAttributes(typeof(DebugApp));

// foreach (CustomAttributeData attribute in attributes)
// {
// Console.WriteLine("{0} is applied to DebugApp", attribute.ToString());
// }

Console.WriteLine(
" Debug attribute is {0} applied to DebugApp " , Attribute.IsDefined( typeof (DebugApp), typeof (DebugAttribute)) ? "" : " not " );
}
}

[Release]
internal class ReleaseApp
{
internal static void ShowAttribute()
{
// IList<CustomAttributeData> attributes = CustomAttributeData.GetCustomAttributes(typeof(ReleaseApp));

// foreach (CustomAttributeData attribute in attributes)
// {
// Console.WriteLine("{0} is applied to ReleaseApp", attribute.ToString());
// }
Console.WriteLine( " Release attribute is {0} applied to ReleaseApp " , Attribute.IsDefined( typeof (ReleaseApp), typeof (ReleaseAttribute)) ? "" : " not " );
}
}

 

 

 

转载于:https://www.cnblogs.com/jerryshi/archive/2009/12/02/1615703.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值