Home Random Page


CATEGORIES:

BiologyChemistryConstructionCultureEcologyEconomyElectronicsFinanceGeographyHistoryInformaticsLawMathematicsMechanicsMedicineOtherPedagogyPhilosophyPhysicsPolicyPsychologySociologySportTourism






Nbsp;   Detecting the Use of a Custom Attribute Without Creating Attribute-Derived Objects

In this section, I discuss an alternate technique for detecting custom attributes applied to a meta- data entry. In some security-conscious scenarios, this alternate technique ensures that no code

in an Attribute-derived class will execute. After all, when you call Attribute’s GetCustom­ Attribute(s) methods, internally, these methods call the attribute class’s constructor and can also call property set accessor methods. In addition, the first access to a type causes the CLR to invoke the type’s type constructor (if it exists). The constructor, set accessor, and type constructor methods could contain code that will execute whenever code is just looking for an attribute. This allows unknown code to run in the AppDomain, and this is a potential security vulnerability.

To discover attributes without allowing attribute class code to execute, you use the System.

Reflection.CustomAttributeData class. This class defines one static method for retrieving the attributes associated with a target: GetCustomAttributes. This method has four overloads: one that takes an Assembly, one that takes a Module, one that takes a ParameterInfo, and one that takes

a MemberInfo. This class is defined in the System.Reflection namespace, which is discussed in Chapter 23. Typically, you’ll use the CustomAttributeData class to analyze attributes in metadata for an assembly that is loaded via Assembly’s static ReflectionOnlyLoad method (also discussed in Chapter 23). Briefly, ReflectionOnlyLoad loads an assembly in such a way that prevents the CLR from executing any code in it; this includes type constructors.

CustomAttributeData’s GetCustomAttributes method acts as a factory. That is, when you call it, it returns a collection of CustomAttributeData objects in an object of type IList<Custom­ AttributeData>. The collection contains one element per custom attribute applied to the specified target. For each CustomAttributeData object, you can query some read-only properties to deter- mine how the attribute object would be constructed and initialized. Specifically, the Constructor

property indicates which constructor method would be called, the ConstructorArguments property returns the arguments that would be passed to this constructor as an instance of IList<Custom­ AttributeTypedArgument>, and the NamedArguments property returns the fields/properties that would be set as an instance of IList<CustomAttributeNamedArgument>. Notice that I say “would be” in the previous sentences because the constructor and set accessor methods will not actually be called—we get the added security by preventing any attribute class methods from executing.

Here’s a modified version of a previous code sample that uses the CustomAttributeData class to securely obtain the attributes applied to various targets.

 

using System;

using System.Diagnostics; using System.Reflection;

using System.Collections.Generic;

 

[assembly: CLSCompliant(true)]

 

[Serializable]




[DefaultMemberAttribute("Main")]

[DebuggerDisplayAttribute("Richter", Name="Jeff", Target=typeof(Program))] public sealed class Program {

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

 

public Program() {

}

 

[CLSCompliant(true)] [STAThread]

public static void Main() {

// Show the set of attributes applied to this type ShowAttributes(typeof(Program));

 

// Get the set of methods associated with the type MemberInfo[] members = typeof(Program).FindMembers(

MemberTypes.Constructor | MemberTypes.Method, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static, Type.FilterName, "*");

 

foreach (MemberInfo member in members) {

// Show the set of attributes applied to this member ShowAttributes(member);

}

}

 

private static void ShowAttributes(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) {

// Display the type of each applied attribute 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:" +

((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 construction:" +

((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();

}

Console.WriteLine();

}

}

 

Building and running this application yields the following output.

 

Attributes applied to Program: System.SerializableAttribute

Constructor called=Void .ctor()

Positional arguments passed to constructor: None Named arguments set after construction: None

 

System.Diagnostics.DebuggerDisplayAttribute Constructor called=Void .ctor(System.String) Positional arguments passed to constructor:

Type=System.String, Value=Richter Named arguments set after construction:

Name=Name, Type=System.String, Value=Jeff Name=Target, Type=System.Type, Value=Program

 

System.Reflection.DefaultMemberAttribute Constructor called=Void .ctor(System.String) Positional arguments passed to constructor:

Type=System.String, Value=Main

Named arguments set after construction: None

 

Attributes applied to DoSomething: System.Diagnostics.ConditionalAttribute

Constructor called=Void .ctor(System.String) Positional arguments passed to constructor:

Type=System.String, Value=Release

Named arguments set after construction: None

 

System.Diagnostics.ConditionalAttribute Constructor called=Void .ctor(System.String) Positional arguments passed to constructor:

Type=System.String, Value=Debug

Named arguments set after construction: None

 

Attributes applied to Main: System.CLSCompliantAttribute

Constructor called=Void .ctor(Boolean) Positional arguments passed to constructor:

Type=System.Boolean, Value=True

Named arguments set after construction: None

 

System.STAThreadAttribute Constructor called=Void .ctor()

Positional arguments passed to constructor: None Named arguments set after construction: None



Date: 2016-03-03; view: 625


<== previous page | next page ==>
Nbsp;   Matching Two Attribute Instances Against Each Other | Nullable Value Types
doclecture.net - lectures - 2014-2024 year. Copyright infringement or personal data (0.015 sec.)