Home Random Page


CATEGORIES:

BiologyChemistryConstructionCultureEcologyEconomyElectronicsFinanceGeographyHistoryInformaticsLawMathematicsMechanicsMedicineOtherPedagogyPhilosophyPhysicsPolicyPsychologySociologySportTourism






Nbsp;   Matching Two Attribute Instances Against Each Other

Now that your code knows how to check whether an instance of an attribute is applied to a target, it might want to check the fields of the attribute to see what values they have. One way to do this is to write code that explicitly checks the values of the attribute class’s fields. However, System.Attribute overrides Object’s Equals method, and internally, this method compares the types of the two objects. If they are not identical, Equals returns false. If the types are identical, then Equals uses reflection to compare the values of the two attribute objects’ fields (by calling Equals for each field). If all the fields match, then true is returned; otherwise, false is returned. You might override Equals in your own attribute class to remove the use of reflec- tion, improving performance.

System.Attribute also exposes a virtual Match method that you can override to provide richer semantics. The default implementation of Match simply calls Equals and returns its result. The fol- lowing code demonstrates how to override Equals and Match (which returns true if one attribute represents a subset of the other) and then shows how Match is used.

 

using System;

 

[Flags]

internal enum Accounts { Savings = 0x0001, Checking = 0x0002, Brokerage = 0x0004

}

 

[AttributeUsage(AttributeTargets.Class)]

internal sealed class AccountsAttribute : Attribute { private Accounts m_accounts;

 

public AccountsAttribute(Accounts accounts) { m_accounts = accounts;

}

 

public override Boolean Match(Object obj) {


// If the base class implements Match and the base class

// is not Attribute, then uncomment the following line.

// if (!base.Match(obj)) return false;

 

// Since 'this' isn't null, if obj is null,

// then the objects can't match

// NOTE: This line may be deleted if you trust

// that the base type implemented Match correctly. if (obj == null) return false;

 

// If the objects are of different types, they can't match

// NOTE: This line may be deleted if you trust

// that the base type implemented Match correctly. if (this.GetType() != obj.GetType()) return false;

 

// Cast obj to our type to access fields. NOTE: This cast

// can't fail since we know objects are of the same type AccountsAttribute other = (AccountsAttribute) obj;

 

// Compare the fields as you see fit

// This example checks if 'this' accounts is a subset

// of others' accounts

if ((other.m_accounts & m_accounts) != m_accounts) return false;

 

return true; // Objects match

}

 

 

public override Boolean Equals(Object obj) {

// If the base class implements Equals, and the base class

// is not Object, then uncomment the following line.

// if (!base.Equals(obj)) return false;

 

// Since 'this' isn't null, if obj is null,

// then the objects can't be equal

// NOTE: This line may be deleted if you trust

// that the base type implemented Equals correctly. if (obj == null) return false;



 

// If the objects are of different types, they can't be equal

// NOTE: This line may be deleted if you trust

// that the base type implemented Equals correctly. if (this.GetType() != obj.GetType()) return false;

 

// Cast obj to our type to access fields. NOTE: This cast

// can't fail since we know objects are of the same type AccountsAttribute other = (AccountsAttribute) obj;

 

// Compare the fields to see if they have the same value

// This example checks if 'this' accounts is the same

// as other's accounts

if (other.m_accounts != m_accounts) return false;


return true; // Objects are equal

}

 

 

// Override GetHashCode since we override Equals public override Int32 GetHashCode() {

return (Int32) m_accounts;

}

}

 

 

[Accounts(Accounts.Savings)]

internal sealed class ChildAccount { }

 

[Accounts(Accounts.Savings | Accounts.Checking | Accounts.Brokerage)] internal sealed class AdultAccount { }

 

 

public sealed class Program { public static void Main() {

CanWriteCheck(new ChildAccount()); CanWriteCheck(new AdultAccount());

 

// This just demonstrates that the method works correctly on a

// type that doesn't have the AccountsAttribute applied to it. CanWriteCheck(new Program());

}

 

private static void CanWriteCheck(Object obj) {

// Construct an instance of the attribute type and initialize it

// to what we are explicitly looking for.

Attribute checking = new AccountsAttribute(Accounts.Checking);

 

// Construct the attribute instance that was applied to the type Attribute validAccounts =

obj.GetType().GetCustomAttribute<AccountsAttribute>(false);

 

// If the attribute was applied to the type AND the

// attribute specifies the "Checking" account, then the

// type can write a check

if ((validAccounts != null) && checking.Match(validAccounts)) { Console.WriteLine("{0} types can write checks.", obj.GetType());

} else {

Console.WriteLine("{0} types can NOT write checks.", obj.GetType());

}

}

}

 

Building and running this application yields the following output.

 

ChildAccount types can NOT write checks. AdultAccount types can write checks.

Program types can NOT write checks.



Date: 2016-03-03; view: 642


<== previous page | next page ==>
Nbsp;   Detecting the Use of a Custom Attribute | Nbsp;   Detecting the Use of a Custom Attribute Without Creating Attribute-Derived Objects
doclecture.net - lectures - 2014-2024 year. Copyright infringement or personal data (0.009 sec.)