#region COPYRIGHT
//
//     THIS IS GENERATED BY TEMPLATE
//     
//     AUTHOR  :     ROYE
//     DATE       :     2010
//
//     COPYRIGHT (C) 2010, TIANXIAHOTEL TECHNOLOGIES CO., LTD. ALL RIGHTS RESERVED.
//
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace System.Reflection
{
    /// <summary>
    /// 保存所有构建动态方法的必需的信息
    /// </summary>
    internal class CallInfo
    {
        public CallInfo(Type targetType, Flags bindingFlags, MemberTypes memberTypes, string name, Type[] parameterTypes, MemberInfo memberInfo)
        {
            TargetType = targetType;
            BindingFlags = bindingFlags;
            MemberTypes = memberTypes;
            Name = name;
            ParamTypes = (parameterTypes == null || parameterTypes.Length == 0) ? Type.EmptyTypes : parameterTypes;
            MemberInfo = memberInfo;
        }

        /// <summary>
        /// Two <c>CallInfo</c> instances are considered equaled if the following properties
        /// are equaled: <c>TargetType</c>, <c>Flags</c>, <c>IsStatic</c>, <c>MemberTypes</c>, <c>Name</c>,
        /// and <c>ParamTypes</c>.
        /// </summary>
        public override bool Equals(object obj)
        {
            var other = obj as CallInfo;
            if (other == null)
            {
                return false;
            }
            if (other == this)
            {
                return true;
            }

            if (other.MemberInfo != MemberInfo ||
                other.TargetType != TargetType ||
                other.Name != Name ||
                other.MemberTypes != MemberTypes ||
                other.BindingFlags != BindingFlags ||
                other.ParamTypes.Length != ParamTypes.Length)
            {
                return false;
            }

            for (int i = 0; i < ParamTypes.Length; i++)
            {
                if (ParamTypes[i] != other.ParamTypes[i])
                {
                    return false;
                }
            }

            return true;
        }

        public override int GetHashCode()
        {
            int hash = TargetType.GetHashCode() + (int)MemberTypes * Name.GetHashCode() + BindingFlags.GetHashCode();
            if (MemberInfo != null)
            {
                hash += MemberInfo.GetHashCode();
            }
            for (int i = 0; i < ParamTypes.Length; i++)
            {
                hash += ParamTypes[i].GetHashCode();
            }
            return hash;
        }

        public Type TargetType { get; private set; }
        public Flags BindingFlags { get; private set; }
        public MemberTypes MemberTypes { get; set; }
        public Type[] ParamTypes { get; private set; }
        public string Name { get; private set; }
        public MemberInfo MemberInfo { get; private set; }

        /// <summary>
        /// The CIL should handle inner struct only when the target type is 
        /// a value type or the wrapper ValueTypeHolder type.  In addition, the call 
        /// must also be executed in the non-static context since static 
        /// context doesn't need to handle inner struct case.
        /// </summary>
        public bool ShouldHandleInnerStruct
        {
            get { return IsTargetTypeStruct && !IsStatic; }
        }

        public bool IsStatic
        {
            get { return BindingFlags.IsSet(Flags.Static); }
        }

        public bool IsTargetTypeStruct
        {
            get { return TargetType.IsValueType; }
        }

        public bool HasNoParam
        {
            get { return ParamTypes == Type.EmptyTypes; }
        }

        public bool HasRefParam
        {
            get { return ParamTypes.Any(t => t.IsByRef); }
        }
    }
}
