//----------------------------------------------------------------------- // // Copyright (c) 2018 Sirenix IVS // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //----------------------------------------------------------------------- namespace VRC.Udon.Serialization.OdinSerializer.Utilities { using System; using System.Globalization; using System.Reflection; /// /// Provides a methods of representing imaginary properties which are unique to serialization. /// /// We aggregate the PropertyInfo associated with this member and return a mangled form of the name. /// /// public sealed class MemberAliasPropertyInfo : PropertyInfo { /// /// The default fake name separator string. /// private const string FakeNameSeparatorString = "+"; private PropertyInfo aliasedProperty; private string mangledName; /// /// Initializes a new instance of the class. /// /// The property to alias. /// The name prefix to use. public MemberAliasPropertyInfo(PropertyInfo prop, string namePrefix) { this.aliasedProperty = prop; this.mangledName = string.Concat(namePrefix, FakeNameSeparatorString, this.aliasedProperty.Name); } /// /// Initializes a new instance of the class. /// /// The property to alias. /// The name prefix to use. /// The separator string to use. public MemberAliasPropertyInfo(PropertyInfo prop, string namePrefix, string separatorString) { this.aliasedProperty = prop; this.mangledName = string.Concat(namePrefix, separatorString, this.aliasedProperty.Name); } /// /// The backing PropertyInfo that is being aliased. /// public PropertyInfo AliasedProperty { get { return this.aliasedProperty; } } /// /// Gets the module in which the type that declares the member represented by the current is defined. /// public override Module Module { get { return this.aliasedProperty.Module; } } /// /// Gets a value that identifies a metadata element. /// public override int MetadataToken { get { return this.aliasedProperty.MetadataToken; } } /// /// Gets the name of the current member. /// public override string Name { get { return this.mangledName; } } /// /// Gets the class that declares this member. /// public override Type DeclaringType { get { return this.aliasedProperty.DeclaringType; } } /// /// Gets the class object that was used to obtain this instance of MemberInfo. /// public override Type ReflectedType { get { return this.aliasedProperty.ReflectedType; } } /// /// Gets the type of the property. /// /// /// The type of the property. /// public override Type PropertyType { get { return this.aliasedProperty.PropertyType; } } /// /// Gets the attributes. /// /// /// The attributes. /// public override PropertyAttributes Attributes { get { return this.aliasedProperty.Attributes; } } /// /// Gets a value indicating whether this instance can read. /// /// /// true if this instance can read; otherwise, false. /// public override bool CanRead { get { return this.aliasedProperty.CanRead; } } /// /// Gets a value indicating whether this instance can write. /// /// /// true if this instance can write; otherwise, false. /// public override bool CanWrite { get { return this.aliasedProperty.CanWrite; } } /// /// When overridden in a derived class, returns an array of all custom attributes applied to this member. /// /// True to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. /// /// An array that contains all the custom attributes applied to this member, or an array with zero elements if no attributes are defined. /// public override object[] GetCustomAttributes(bool inherit) { return this.aliasedProperty.GetCustomAttributes(inherit); } /// /// When overridden in a derived class, returns an array of custom attributes applied to this member and identified by . /// /// The type of attribute to search for. Only attributes that are assignable to this type are returned. /// True to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. /// /// An array of custom attributes applied to this member, or an array with zero elements if no attributes assignable to have been applied. /// public override object[] GetCustomAttributes(Type attributeType, bool inherit) { return this.aliasedProperty.GetCustomAttributes(attributeType, inherit); } /// /// When overridden in a derived class, indicates whether one or more attributes of the specified type or of its derived types is applied to this member. /// /// The type of custom attribute to search for. The search includes derived types. /// True to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events; see Remarks. /// /// True if one or more instances of or any of its derived types is applied to this member; otherwise, false. /// public override bool IsDefined(Type attributeType, bool inherit) { return this.aliasedProperty.IsDefined(attributeType, inherit); } /// /// Returns an array whose elements reflect the public and, if specified, non-public get, set, and other accessors of the property reflected by the current instance. /// /// Indicates whether non-public methods should be returned in the MethodInfo array. true if non-public methods are to be included; otherwise, false. /// /// An array of objects whose elements reflect the get, set, and other accessors of the property reflected by the current instance. If is true, this array contains public and non-public get, set, and other accessors. If is false, this array contains only public get, set, and other accessors. If no accessors with the specified visibility are found, this method returns an array with zero (0) elements. /// public override MethodInfo[] GetAccessors(bool nonPublic) { return this.aliasedProperty.GetAccessors(nonPublic); } /// /// When overridden in a derived class, returns the public or non-public get accessor for this property. /// /// Indicates whether a non-public get accessor should be returned. true if a non-public accessor is to be returned; otherwise, false. /// /// A MethodInfo object representing the get accessor for this property, if is true. Returns null if is false and the get accessor is non-public, or if is true but no get accessors exist. /// public override MethodInfo GetGetMethod(bool nonPublic) { return this.aliasedProperty.GetGetMethod(nonPublic); } /// /// Gets the index parameters of the property. /// /// The index parameters of the property. public override ParameterInfo[] GetIndexParameters() { return this.aliasedProperty.GetIndexParameters(); } /// /// When overridden in a derived class, returns the set accessor for this property. /// /// Indicates whether the accessor should be returned if it is non-public. true if a non-public accessor is to be returned; otherwise, false. /// /// Value Condition A object representing the Set method for this property. The set accessor is public.-or- is true and the set accessor is non-public. null is true, but the property is read-only.-or- is false and the set accessor is non-public.-or- There is no set accessor. /// public override MethodInfo GetSetMethod(bool nonPublic) { return this.aliasedProperty.GetSetMethod(nonPublic); } /// /// Gets the value of the property on the given instance. /// /// The object to invoke the getter on. /// The to invoke with. /// The binder to use. /// The indices to use. /// The culture to use. /// The value of the property on the given instance. public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { return this.aliasedProperty.GetValue(obj, invokeAttr, binder, index, culture); } /// /// Sets the value of the property on the given instance. /// /// The object to set the value on. /// The value to set. /// The to invoke with. /// The binder to use. /// The indices to use. /// The culture to use. public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { this.aliasedProperty.SetValue(obj, value, invokeAttr, binder, index, culture); } } }