forked from cgvr/DeltaVR
		
	
		
			
				
	
	
		
			222 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			222 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
//
 | 
						|
// Author:
 | 
						|
//   Jb Evain (jbevain@gmail.com)
 | 
						|
//
 | 
						|
// Copyright (c) 2008 - 2015 Jb Evain
 | 
						|
// Copyright (c) 2008 - 2011 Novell, Inc.
 | 
						|
//
 | 
						|
// Licensed under the MIT/X11 license.
 | 
						|
//
 | 
						|
 | 
						|
using MonoFN.Collections.Generic;
 | 
						|
using System;
 | 
						|
using System.Diagnostics;
 | 
						|
using System.Threading;
 | 
						|
 | 
						|
namespace MonoFN.Cecil {
 | 
						|
 | 
						|
	public struct CustomAttributeArgument {
 | 
						|
 | 
						|
		readonly TypeReference type;
 | 
						|
		readonly object value;
 | 
						|
 | 
						|
		public TypeReference Type {
 | 
						|
			get { return type; }
 | 
						|
		}
 | 
						|
 | 
						|
		public object Value {
 | 
						|
			get { return value; }
 | 
						|
		}
 | 
						|
 | 
						|
		public CustomAttributeArgument (TypeReference type, object value)
 | 
						|
		{
 | 
						|
			Mixin.CheckType (type);
 | 
						|
			this.type = type;
 | 
						|
			this.value = value;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	public struct CustomAttributeNamedArgument {
 | 
						|
 | 
						|
		readonly string name;
 | 
						|
		readonly CustomAttributeArgument argument;
 | 
						|
 | 
						|
		public string Name {
 | 
						|
			get { return name; }
 | 
						|
		}
 | 
						|
 | 
						|
		public CustomAttributeArgument Argument {
 | 
						|
			get { return argument; }
 | 
						|
		}
 | 
						|
 | 
						|
		public CustomAttributeNamedArgument (string name, CustomAttributeArgument argument)
 | 
						|
		{
 | 
						|
			Mixin.CheckName (name);
 | 
						|
			this.name = name;
 | 
						|
			this.argument = argument;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	public interface ICustomAttribute {
 | 
						|
 | 
						|
		TypeReference AttributeType { get; }
 | 
						|
 | 
						|
		bool HasFields { get; }
 | 
						|
		bool HasProperties { get; }
 | 
						|
		bool HasConstructorArguments { get; }
 | 
						|
		Collection<CustomAttributeNamedArgument> Fields { get; }
 | 
						|
		Collection<CustomAttributeNamedArgument> Properties { get; }
 | 
						|
		Collection<CustomAttributeArgument> ConstructorArguments { get; }
 | 
						|
	}
 | 
						|
 | 
						|
	[DebuggerDisplay ("{AttributeType}")]
 | 
						|
	public sealed class CustomAttribute : ICustomAttribute {
 | 
						|
 | 
						|
		internal CustomAttributeValueProjection projection;
 | 
						|
		readonly internal uint signature;
 | 
						|
		internal bool resolved;
 | 
						|
		MethodReference constructor;
 | 
						|
		byte [] blob;
 | 
						|
		internal Collection<CustomAttributeArgument> arguments;
 | 
						|
		internal Collection<CustomAttributeNamedArgument> fields;
 | 
						|
		internal Collection<CustomAttributeNamedArgument> properties;
 | 
						|
 | 
						|
		public MethodReference Constructor {
 | 
						|
			get { return constructor; }
 | 
						|
			set { constructor = value; }
 | 
						|
		}
 | 
						|
 | 
						|
		public TypeReference AttributeType {
 | 
						|
			get { return constructor.DeclaringType; }
 | 
						|
		}
 | 
						|
 | 
						|
		public bool IsResolved {
 | 
						|
			get { return resolved; }
 | 
						|
		}
 | 
						|
 | 
						|
		public bool HasConstructorArguments {
 | 
						|
			get {
 | 
						|
				Resolve ();
 | 
						|
 | 
						|
				return !arguments.IsNullOrEmpty ();
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		public Collection<CustomAttributeArgument> ConstructorArguments {
 | 
						|
			get {
 | 
						|
				Resolve ();
 | 
						|
 | 
						|
				if (arguments == null)
 | 
						|
					Interlocked.CompareExchange (ref arguments, new Collection<CustomAttributeArgument> (), null);
 | 
						|
 | 
						|
				return arguments;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		public bool HasFields {
 | 
						|
			get {
 | 
						|
				Resolve ();
 | 
						|
 | 
						|
				return !fields.IsNullOrEmpty ();
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		public Collection<CustomAttributeNamedArgument> Fields {
 | 
						|
			get {
 | 
						|
				Resolve ();
 | 
						|
 | 
						|
				if (fields == null)
 | 
						|
					Interlocked.CompareExchange (ref fields, new Collection<CustomAttributeNamedArgument> (), null);
 | 
						|
 | 
						|
				return fields;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		public bool HasProperties {
 | 
						|
			get {
 | 
						|
				Resolve ();
 | 
						|
 | 
						|
				return !properties.IsNullOrEmpty ();
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		public Collection<CustomAttributeNamedArgument> Properties {
 | 
						|
			get {
 | 
						|
				Resolve ();
 | 
						|
 | 
						|
				if (properties == null)
 | 
						|
					Interlocked.CompareExchange (ref properties, new Collection<CustomAttributeNamedArgument> (), null);
 | 
						|
 | 
						|
				return properties;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		internal bool HasImage {
 | 
						|
			get { return constructor != null && constructor.HasImage; }
 | 
						|
		}
 | 
						|
 | 
						|
		internal ModuleDefinition Module {
 | 
						|
			get { return constructor.Module; }
 | 
						|
		}
 | 
						|
 | 
						|
		internal CustomAttribute (uint signature, MethodReference constructor)
 | 
						|
		{
 | 
						|
			this.signature = signature;
 | 
						|
			this.constructor = constructor;
 | 
						|
			this.resolved = false;
 | 
						|
		}
 | 
						|
 | 
						|
		public CustomAttribute (MethodReference constructor)
 | 
						|
		{
 | 
						|
			this.constructor = constructor;
 | 
						|
			this.resolved = true;
 | 
						|
		}
 | 
						|
 | 
						|
		public CustomAttribute (MethodReference constructor, byte [] blob)
 | 
						|
		{
 | 
						|
			this.constructor = constructor;
 | 
						|
			this.resolved = false;
 | 
						|
			this.blob = blob;
 | 
						|
		}
 | 
						|
 | 
						|
		public byte [] GetBlob ()
 | 
						|
		{
 | 
						|
			if (blob != null)
 | 
						|
				return blob;
 | 
						|
 | 
						|
			if (!HasImage)
 | 
						|
				throw new NotSupportedException ();
 | 
						|
 | 
						|
			return Module.Read (ref blob, this, (attribute, reader) => reader.ReadCustomAttributeBlob (attribute.signature));
 | 
						|
		}
 | 
						|
 | 
						|
		void Resolve ()
 | 
						|
		{
 | 
						|
			if (resolved || !HasImage)
 | 
						|
				return;
 | 
						|
 | 
						|
			lock (Module.SyncRoot) {
 | 
						|
				if (resolved)
 | 
						|
					return;
 | 
						|
 | 
						|
				Module.Read (this, (attribute, reader) => {
 | 
						|
					try {
 | 
						|
						reader.ReadCustomAttributeSignature (attribute);
 | 
						|
						resolved = true;
 | 
						|
					}
 | 
						|
					catch (ResolutionException) {
 | 
						|
						if (arguments != null)
 | 
						|
							arguments.Clear ();
 | 
						|
						if (fields != null)
 | 
						|
							fields.Clear ();
 | 
						|
						if (properties != null)
 | 
						|
							properties.Clear ();
 | 
						|
 | 
						|
						resolved = false;
 | 
						|
					}
 | 
						|
				});
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |