using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Globalization; using ILRuntime.CLR.Method; using ILRuntime.CLR.TypeSystem; namespace ILRuntime.Reflection { public class ILRuntimePropertyInfo : PropertyInfo { ILMethod getter, setter; ILType dType; Mono.Cecil.PropertyDefinition definition; ILRuntime.Runtime.Enviorment.AppDomain appdomain; ILRuntimeParameterInfo[] parameters; Attribute[] customAttributes; Type[] attributeTypes; public ILMethod Getter { get { return getter; } set { getter = value; } } public ILMethod Setter { get { return setter; } set { setter = value; } } public bool IsPublic { get { if (getter != null) return getter.Definition.IsPublic; else return setter.Definition.IsPublic; } } public bool IsStatic { get { if (getter != null) return getter.IsStatic; else return setter.IsStatic; } } public ILRuntimePropertyInfo(Mono.Cecil.PropertyDefinition definition, ILType dType) { this.definition = definition; this.dType = dType; appdomain = dType.AppDomain; parameters = new ILRuntimeParameterInfo[definition.Parameters.Count]; for (int i = 0; i < definition.Parameters.Count; i++) { var pd = definition.Parameters[i]; var parameterType = dType.AppDomain.GetType(pd.ParameterType, null, null); parameters[i] = new ILRuntimeParameterInfo(pd, parameterType, this, appdomain); } } void InitializeCustomAttribute() { customAttributes = new Attribute[definition.CustomAttributes.Count]; attributeTypes = new Type[customAttributes.Length]; for (int i = 0; i < definition.CustomAttributes.Count; i++) { var attribute = definition.CustomAttributes[i]; var at = appdomain.GetType(attribute.AttributeType, null, null); try { Attribute ins = attribute.CreateInstance(at, appdomain) as Attribute; attributeTypes[i] = at.ReflectionType; customAttributes[i] = ins; } catch { attributeTypes[i] = typeof(Attribute); } } } public override string Name { get { return definition.Name; } } public override Type ReflectedType { get { return dType.ReflectionType; } } public override PropertyAttributes Attributes { get { return PropertyAttributes.None; } } public override bool CanRead { get { return getter != null; } } public override bool CanWrite { get { return setter != null; } } public override Type PropertyType { get { if (getter != null) return getter.ReturnType.ReflectionType; else { return setter.Parameters[0].ReflectionType; } } } public ILRuntime.Mono.Cecil.TypeReference Definition { get { return definition.GetMethod != null ? definition.GetMethod.ReturnType : definition.SetMethod.Parameters[0].ParameterType; } } public override Type DeclaringType { get { return dType.ReflectionType; } } public override object[] GetCustomAttributes(bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); return customAttributes; } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); List res = new List(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i].Equals(attributeType)) { res.Add(customAttributes[i]); } } return res.ToArray(); } public override bool IsDefined(Type attributeType, bool inherit) { if (customAttributes == null) InitializeCustomAttribute(); for (int i = 0; i < customAttributes.Length; i++) { if (attributeTypes[i].Equals(attributeType)) { return true; } } return false; } public override MethodInfo[] GetAccessors(bool nonPublic) { throw new NotImplementedException(); } public override MethodInfo GetGetMethod(bool nonPublic) { if (getter != null) return getter.ReflectionMethodInfo; return null; } public override ParameterInfo[] GetIndexParameters() { return parameters; } public override MethodInfo GetSetMethod(bool nonPublic) { if (setter != null) return setter.ReflectionMethodInfo; return null; } public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { var indexCnt = index != null ? index.Length : 0; if (getter.ParameterCount <= indexCnt) { using (var ctx = appdomain.BeginInvoke(getter)) { if (!IsStatic) ctx.PushObject(obj); for (int i = 0; i < getter.ParameterCount; i++) { ctx.PushObject(index[i], !getter.Parameters[i].IsValueType); } ctx.Invoke(); return ctx.ReadObject(getter.ReturnType.TypeForCLR); } } else throw new ArgumentException("Index count mismatch"); } public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { var indexCnt = index != null ? index.Length : 0; if (setter.ParameterCount <= indexCnt + 1) { using (var ctx = appdomain.BeginInvoke(setter)) { if (!IsStatic) ctx.PushObject(obj); for (int i = 0; i < setter.ParameterCount - 1; i++) { ctx.PushObject(index[i], !setter.Parameters[i].IsValueType); } ctx.PushObject(value, !setter.Parameters[setter.ParameterCount - 1].IsValueType); ctx.Invoke(); } } else throw new ArgumentException("Index count mismatch"); } public override string ToString() { return definition == null ? base.ToString() : definition.ToString(); } } }