a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
451 lines
14 KiB
C#
451 lines
14 KiB
C#
//
|
|
// System.Attribute.cs
|
|
//
|
|
// Authors:
|
|
// Miguel de Icaza (miguel@ximian.com) - Original
|
|
// Nick D. Drochak II (ndrochak@gol.com) - Implemented most of the guts
|
|
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
|
|
//
|
|
// (C) 2002, 2003 Ximian, Inc. http://www.ximian.com
|
|
// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace System
|
|
{
|
|
[AttributeUsage (AttributeTargets.All)]
|
|
[Serializable]
|
|
[ComVisible (true)]
|
|
[ComDefaultInterface (typeof (_Attribute))]
|
|
[ClassInterfaceAttribute (ClassInterfaceType.None)]
|
|
#if MOBILE
|
|
public abstract class Attribute {
|
|
#else
|
|
public abstract class Attribute : _Attribute {
|
|
#endif
|
|
protected Attribute ()
|
|
{
|
|
}
|
|
|
|
public virtual object TypeId {
|
|
get {
|
|
// Derived classes should override this default behaviour as appropriate
|
|
return this.GetType ();
|
|
}
|
|
}
|
|
|
|
private static void CheckParameters (object element, Type attributeType)
|
|
{
|
|
// neither parameter is allowed to be null
|
|
if (element == null)
|
|
throw new ArgumentNullException ("element");
|
|
|
|
if (attributeType == null)
|
|
throw new ArgumentNullException ("attributeType");
|
|
|
|
if (!typeof (Attribute).IsAssignableFrom (attributeType))
|
|
throw new ArgumentException (Locale.GetText (
|
|
"Type is not derived from System.Attribute."), "attributeType");
|
|
}
|
|
|
|
private static Attribute FindAttribute (object[] attributes)
|
|
{
|
|
// if there exists more than one attribute of the given type, throw an exception
|
|
if (attributes.Length > 1) {
|
|
throw new AmbiguousMatchException (Locale.GetText (
|
|
"<element> has more than one attribute of type <attribute_type>"));
|
|
}
|
|
|
|
if (attributes.Length < 1)
|
|
return null;
|
|
|
|
// tested above for '> 1' and and '< 1', so only '== 1' is left,
|
|
// i.e. we found the attribute
|
|
return (Attribute) attributes[0];
|
|
}
|
|
|
|
public static Attribute GetCustomAttribute (ParameterInfo element, Type attributeType)
|
|
{
|
|
return GetCustomAttribute (element, attributeType, true);
|
|
}
|
|
|
|
public static Attribute GetCustomAttribute (MemberInfo element, Type attributeType)
|
|
{
|
|
return GetCustomAttribute (element, attributeType, true);
|
|
}
|
|
|
|
public static Attribute GetCustomAttribute (Assembly element, Type attributeType)
|
|
{
|
|
return GetCustomAttribute (element, attributeType, true);
|
|
}
|
|
|
|
public static Attribute GetCustomAttribute (Module element, Type attributeType)
|
|
{
|
|
return GetCustomAttribute (element, attributeType, true);
|
|
}
|
|
|
|
public static Attribute GetCustomAttribute (Module element, Type attributeType, bool inherit)
|
|
{
|
|
// neither parameter is allowed to be null
|
|
CheckParameters (element, attributeType);
|
|
|
|
// Module inheritance hierarchies CAN NOT be searched for attributes, so the second
|
|
// parameter of GetCustomAttributes () is IGNORED.
|
|
object[] attributes = element.GetCustomAttributes (attributeType, inherit);
|
|
|
|
return FindAttribute (attributes);
|
|
}
|
|
|
|
public static Attribute GetCustomAttribute (Assembly element, Type attributeType, bool inherit)
|
|
{
|
|
// neither parameter is allowed to be null
|
|
CheckParameters (element, attributeType);
|
|
|
|
// Assembly inheritance hierarchies CAN NOT be searched for attributes, so the second
|
|
// parameter of GetCustomAttributes () is IGNORED.
|
|
object[] attributes = element.GetCustomAttributes (attributeType, inherit);
|
|
|
|
return FindAttribute (attributes);
|
|
}
|
|
|
|
public static Attribute GetCustomAttribute (ParameterInfo element, Type attributeType, bool inherit)
|
|
{
|
|
// neither parameter is allowed to be null
|
|
CheckParameters (element, attributeType);
|
|
|
|
object[] attributes = GetCustomAttributes (element, attributeType, inherit);
|
|
|
|
return FindAttribute (attributes);
|
|
}
|
|
|
|
public static Attribute GetCustomAttribute (MemberInfo element, Type attributeType, bool inherit)
|
|
{
|
|
// neither parameter is allowed to be null
|
|
CheckParameters (element, attributeType);
|
|
|
|
// MemberInfo inheritance hierarchies can be searched for attributes, so the second
|
|
// parameter of GetCustomAttribute () is respected.
|
|
return MonoCustomAttrs.GetCustomAttribute (element, attributeType, inherit);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (Assembly element)
|
|
{
|
|
return GetCustomAttributes (element, true);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (ParameterInfo element)
|
|
{
|
|
return GetCustomAttributes (element, true);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (MemberInfo element)
|
|
{
|
|
return GetCustomAttributes (element, true);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (Module element)
|
|
{
|
|
return GetCustomAttributes (element, true);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (Assembly element, Type attributeType)
|
|
{
|
|
return GetCustomAttributes (element, attributeType, true);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (Module element, Type attributeType)
|
|
{
|
|
return GetCustomAttributes (element, attributeType, true);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (ParameterInfo element, Type attributeType)
|
|
{
|
|
return GetCustomAttributes (element, attributeType, true);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (MemberInfo element, Type type)
|
|
{
|
|
return GetCustomAttributes (element, type, true);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (Assembly element, Type attributeType, bool inherit)
|
|
{
|
|
// element parameter is not allowed to be null
|
|
CheckParameters (element, attributeType);
|
|
|
|
return (Attribute []) element.GetCustomAttributes (attributeType, inherit);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (ParameterInfo element, Type attributeType, bool inherit)
|
|
{
|
|
// element parameter is not allowed to be null
|
|
CheckParameters (element, attributeType);
|
|
|
|
Attribute [] attributes;
|
|
if (inherit && TryGetParamCustomAttributes (element, attributeType, out attributes))
|
|
return attributes;
|
|
|
|
return (Attribute []) element.GetCustomAttributes (attributeType, inherit);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (Module element, Type attributeType, bool inherit)
|
|
{
|
|
// element parameter is not allowed to be null
|
|
CheckParameters (element, attributeType);
|
|
|
|
return (Attribute []) element.GetCustomAttributes (attributeType, inherit);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (MemberInfo element, Type type, bool inherit)
|
|
{
|
|
// element parameter is not allowed to be null
|
|
CheckParameters (element, type);
|
|
|
|
// MS ignores the inherit param in PropertyInfo's ICustomAttributeProvider
|
|
// implementation, but not in the Attributes, so directly get the attributes
|
|
// from MonoCustomAttrs instead of going throught the PropertyInfo's
|
|
// ICustomAttributeProvider
|
|
MemberTypes mtype = element.MemberType;
|
|
if (mtype == MemberTypes.Property)
|
|
return (Attribute []) MonoCustomAttrs.GetCustomAttributes (element, type, inherit);
|
|
return (Attribute []) element.GetCustomAttributes (type, inherit);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (Module element, bool inherit)
|
|
{
|
|
return GetCustomAttributes (element, typeof (Attribute), inherit);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (Assembly element, bool inherit)
|
|
{
|
|
return GetCustomAttributes (element, typeof (Attribute), inherit);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (MemberInfo element, bool inherit)
|
|
{
|
|
return GetCustomAttributes (element, typeof (Attribute), inherit);
|
|
}
|
|
|
|
public static Attribute[] GetCustomAttributes (ParameterInfo element, bool inherit)
|
|
{
|
|
// element parameter is not allowed to be null
|
|
CheckParameters (element, typeof (Attribute));
|
|
|
|
return GetCustomAttributes (element, typeof (Attribute), inherit);
|
|
}
|
|
|
|
public override int GetHashCode ()
|
|
{
|
|
int result = GetType ().GetHashCode ();
|
|
|
|
FieldInfo[] fields = GetType ().GetFields (BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
|
foreach (FieldInfo field in fields) {
|
|
object value = field.GetValue (this);
|
|
result ^= value == null ? 0 : value.GetHashCode ();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public virtual bool IsDefaultAttribute ()
|
|
{
|
|
// Derived classes should override this default behaviour as appropriate
|
|
return false;
|
|
}
|
|
|
|
public static bool IsDefined (Module element, Type attributeType)
|
|
{
|
|
return IsDefined (element, attributeType, false);
|
|
}
|
|
|
|
public static bool IsDefined (ParameterInfo element, Type attributeType)
|
|
{
|
|
return IsDefined (element, attributeType, true);
|
|
}
|
|
|
|
public static bool IsDefined (MemberInfo element, Type attributeType)
|
|
{
|
|
return IsDefined (element, attributeType, true);
|
|
}
|
|
|
|
public static bool IsDefined (Assembly element, Type attributeType)
|
|
{
|
|
return IsDefined (element, attributeType, true);
|
|
}
|
|
|
|
public static bool IsDefined (MemberInfo element, Type attributeType, bool inherit)
|
|
{
|
|
CheckParameters (element, attributeType);
|
|
|
|
MemberTypes mtype = element.MemberType;
|
|
if (mtype != MemberTypes.Constructor && mtype != MemberTypes.Event &&
|
|
mtype != MemberTypes.Field && mtype != MemberTypes.Method &&
|
|
mtype != MemberTypes.Property && mtype != MemberTypes.TypeInfo &&
|
|
mtype != MemberTypes.NestedType)
|
|
throw new NotSupportedException (Locale.GetText (
|
|
"Element is not a constructor, method, property, event, type or field."));
|
|
// MS ignores the inherit param in PropertyInfo's ICustomAttributeProvider
|
|
// implementation, but not in the Attributes, so directly get the attributes
|
|
// from MonoCustomAttrs instead of going throught the PropertyInfo's
|
|
// ICustomAttributeProvider
|
|
if (mtype == MemberTypes.Property)
|
|
return MonoCustomAttrs.IsDefined (element, attributeType, inherit);
|
|
return ((MemberInfo) element).IsDefined (attributeType, inherit);
|
|
}
|
|
|
|
public static bool IsDefined (Assembly element, Type attributeType, bool inherit)
|
|
{
|
|
CheckParameters (element, attributeType);
|
|
|
|
return element.IsDefined (attributeType, inherit);
|
|
}
|
|
|
|
public static bool IsDefined (Module element, Type attributeType, bool inherit)
|
|
{
|
|
CheckParameters (element, attributeType);
|
|
|
|
return element.IsDefined (attributeType, inherit);
|
|
}
|
|
|
|
public static bool IsDefined (ParameterInfo element, Type attributeType, bool inherit)
|
|
{
|
|
CheckParameters (element, attributeType);
|
|
|
|
if (element.IsDefined (attributeType, inherit))
|
|
return true;
|
|
|
|
if (inherit)
|
|
return IsDefinedOnParameter (element, attributeType);
|
|
|
|
return false;
|
|
}
|
|
|
|
static bool IsDefinedOnParameter (ParameterInfo parameter, Type attributeType)
|
|
{
|
|
var member = parameter.Member;
|
|
if (member.MemberType != MemberTypes.Method)
|
|
return false;
|
|
|
|
var method = ((MethodInfo) member).GetBaseMethod ();
|
|
|
|
while (true) {
|
|
var param = method.GetParametersInternal () [parameter.Position];
|
|
if (param.IsDefined (attributeType, false))
|
|
return true;
|
|
|
|
var base_method = method.GetBaseMethod ();
|
|
if (base_method == method)
|
|
break;
|
|
|
|
method = base_method;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static bool TryGetParamCustomAttributes (ParameterInfo parameter, Type attributeType, out Attribute [] attributes)
|
|
{
|
|
attributes = null;
|
|
|
|
if (parameter.Member.MemberType != MemberTypes.Method)
|
|
return false;
|
|
|
|
var method = (MethodInfo) parameter.Member;
|
|
var definition = method.GetBaseDefinition ();
|
|
|
|
if (method == definition)
|
|
return false;
|
|
|
|
var types = new List<Type> ();
|
|
var custom_attributes = new List<Attribute> ();
|
|
|
|
while (true) {
|
|
var param = method.GetParametersInternal () [parameter.Position];
|
|
var param_attributes = (Attribute []) param.GetCustomAttributes (attributeType, false);
|
|
foreach (var param_attribute in param_attributes) {
|
|
var param_type = param_attribute.GetType ();
|
|
if (types.Contains (param_type))
|
|
continue;
|
|
|
|
types.Add (param_type);
|
|
custom_attributes.Add (param_attribute);
|
|
}
|
|
|
|
var base_method = method.GetBaseMethod ();
|
|
if (base_method == method)
|
|
break;
|
|
|
|
method = base_method;
|
|
}
|
|
|
|
attributes = (Attribute []) Array.CreateInstance (attributeType, custom_attributes.Count);
|
|
custom_attributes.CopyTo (attributes, 0);
|
|
|
|
return true;
|
|
}
|
|
|
|
public virtual bool Match (object obj)
|
|
{
|
|
// default action is the same as Equals.
|
|
// Derived classes should override as appropriate
|
|
return this.Equals (obj);
|
|
}
|
|
|
|
public override bool Equals (object obj)
|
|
{
|
|
if (obj == null || !(obj is Attribute))
|
|
return false;
|
|
|
|
//
|
|
// This is needed because Attribute.Equals does a deep
|
|
// compare. Ran into this with vbnc
|
|
//
|
|
return ValueType.DefaultEquals (this, obj);
|
|
}
|
|
|
|
#if !MOBILE
|
|
void _Attribute.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
void _Attribute.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
void _Attribute.GetTypeInfoCount (out uint pcTInfo)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
void _Attribute.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams,
|
|
IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
#endif
|
|
}
|
|
}
|