#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.Emit
{
    internal class AttributeSetEmitter : AttributeEmitter
    {
        public AttributeSetEmitter(CallInfo_ callInfo, DelegateCache cache)
            : base(callInfo, cache)
        {
        }

        protected override object Invoke(Delegate action)
        {
            if (CallInfo.IsStatic)
            {
                var invocation = (StaticAttributeSetter)action;
                invocation.Invoke(CallInfo.Parameters[0]);
            }
            else
            {
                var invocation = (AttributeSetter)action;
                invocation.Invoke(CallInfo.Target, CallInfo.Parameters[0]);
            }
            return null;
        }

        protected override Delegate CreateDelegate()
        {
            MemberInfo member = GetAttribute(CallInfo);
            var method = CallInfo.IsStatic ?
                CreateDynamicMethod("setter", CallInfo.TargetType, null, new[] { Constants.ObjectType }) :
                CreateDynamicMethod("setter", CallInfo.TargetType, null, new[] { Constants.ObjectType, Constants.ObjectType });

            ILGenerator generator = method.GetILGenerator();

            generator.Emit(OpCodes.Ldarg_0);
            if (!CallInfo.IsStatic)
            {
                generator.Emit(OpCodes.Castclass, CallInfo.TargetType);
                generator.Emit(OpCodes.Ldarg_1);
            }

            Type memberType = member is FieldInfo ? ((FieldInfo)member).FieldType : ((PropertyInfo)member).PropertyType;

            UnboxOrCast(generator, memberType);

            if (member.MemberType == MemberTypes.Field)
            {
                generator.Emit(CallInfo.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, (FieldInfo)member);
            }
            else
            {
                MethodInfo setMethod = GetPropertySetMethod();
                generator.Emit(CallInfo.IsStatic ? OpCodes.Call : OpCodes.Callvirt, setMethod);
            }

            generator.Emit(OpCodes.Ret);

            return CallInfo.IsStatic ?
                method.CreateDelegate(typeof(StaticAttributeSetter)) :
                method.CreateDelegate(typeof(AttributeSetter));
        }
    }
}
