private static void CreatePropertySetterDelegate(Builder builder, PropertyBuilderInfo member, Method propertySetter)
        {
            var iList      = new __IList(builder);
            var setterCode = propertySetter.NewCode();

            if (!member.Property.BackingField.FieldType.IsGenericType)
            {
                var extensions = new __Extensions(builder);

                if (member.Property.BackingField.FieldType.ParameterlessContructor != null && member.Property.BackingField.FieldType.ParameterlessContructor.IsPublic)
                {
                    setterCode.Load(member.Property.BackingField).IsNull().Then(y =>
                                                                                y.Assign(member.Property.BackingField).Set(propertySetter.NewCode()
                                                                                                                           .NewObj(member.Property.BackingField.FieldType.ParameterlessContructor)));
                }

                // Only this if the property implements idisposable
                if (member.Property.BackingField.FieldType.Implements(typeof(IDisposable)))
                {
                    setterCode.Call(extensions.TryDisposeInternal, member.Property.BackingField);
                }

                setterCode.Load(propertySetter.NewCode().GetParameter(0)).IsNull().Then(x =>
                {
                    // Just clear if its clearable
                    if (member.Property.BackingField.FieldType.Implements(iList.Type.Fullname))
                    {
                        x.Load(member.Property.BackingField).Callvirt(iList.Clear).Return();
                    }
                    // Otherwise if the property is not a value type and nullable
                    else if (!member.Property.BackingField.FieldType.IsValueType || member.Property.BackingField.FieldType.IsNullable || member.Property.BackingField.FieldType.IsArray)
                    {
                        x.Assign(member.Property.BackingField).Set(null).Return();
                    }
                    else // otherwise... throw an exception
                    {
                        x.ThrowNew(typeof(NotSupportedException), "Value types does not accept null values.");
                    }
                });

                if (member.Property.BackingField.FieldType.IsArray)
                {
                    setterCode.Load(propertySetter.NewCode().GetParameter(0)).Is(typeof(IEnumerable))
                    .Then(x => x.Assign(member.Property.BackingField).Set(propertySetter.NewCode().GetParameter(0)).Return())
                    .ThrowNew(typeof(NotSupportedException), "Value does not inherits from IEnumerable");
                }
                else if (member.Property.BackingField.FieldType.Implements(iList.Type.Fullname) && member.Property.BackingField.FieldType.ParameterlessContructor != null)
                {
                    var addRange = member.Property.BackingField.FieldType.GetMethod("AddRange", 1, false);
                    if (addRange == null)
                    {
                        var add   = member.Property.BackingField.FieldType.GetMethod("Add", 1);
                        var array = setterCode.CreateVariable(member.Property.BackingField.FieldType.ChildType.MakeArray());
                        setterCode.Assign(array).Set(propertySetter.NewCode().GetParameter(0));
                        setterCode.For(array, (x, item) => x.Load(member.Property.BackingField).Callvirt(add, item));
                        if (!add.ReturnType.IsVoid)
                        {
                            setterCode.Pop();
                        }
                    }
                    else
                    {
                        setterCode.Load(member.Property.BackingField).Callvirt(addRange, propertySetter.NewCode().GetParameter(0));
                    }
                }
                else if (member.Property.BackingField.FieldType.IsEnum)
                {
                    // Enums requires special threatment
                    setterCode.Load(propertySetter.NewCode().GetParameter(0)).Is(typeof(string)).Then(x =>
                    {
                        var stringVariable = setterCode.CreateVariable(typeof(string));
                        setterCode.Assign(stringVariable).Set(x.NewCode().GetParameter(0));
                        setterCode.Assign(member.Property.BackingField).Set(stringVariable).Return();
                    });

                    setterCode.Assign(member.Property.BackingField).Set(propertySetter.NewCode().GetParameter(0));
                }
                else
                {
                    setterCode.Assign(member.Property.BackingField).Set(propertySetter.NewCode().GetParameter(0));
                }
            }
            else
            {
                setterCode.Assign(member.Property.BackingField).Set(propertySetter.NewCode().GetParameter(0));
            }

            setterCode.Return().Replace();
        }
        private static void CreateSetterDelegate(Builder builder, Method setterDelegateMethod, BuilderType propertyType,
                                                 Func <ICode, ICode> loadValue, Func <ICode, Func <object>, ICode> setValue)
        {
            var extensions = new __Extensions();
            var iList      = new __IList();
            var setterCode = setterDelegateMethod.NewCode();

            if (propertyType.ParameterlessContructor != null && propertyType.ParameterlessContructor.IsPublic)
            {
                loadValue(setterCode).IsNull().Then(y => setValue(y, () => setterCode.NewCode().NewObj(propertyType.ParameterlessContructor)));
            }

            // Only this if the property implements idisposable
            if (propertyType.Implements(typeof(IDisposable)))
            {
                setterCode.Call(extensions.TryDisposeInternal, loadValue(setterCode.NewCode()));
            }

            setterCode.Load(Crumb.GetParameter(0)).IsNull().Then(x =>
            {
                // Just clear if its clearable
                if (propertyType.Implements(__IList.Type.Fullname))
                {
                    loadValue(x).Callvirt(iList.Clear).Return();
                }
                // Otherwise if the property is not a value type and nullable
                else if (!propertyType.IsValueType || propertyType.IsNullable || propertyType.IsArray)
                {
                    setValue(x, () => null).Return();
                }
                else // otherwise... throw an exception
                {
                    x.ThrowNew(typeof(NotSupportedException), "Value types does not accept null values.");
                }
            });

            if (propertyType.IsArray)
            {
                setterCode.Load(Crumb.GetParameter(0)).Is(typeof(IEnumerable))
                .Then(x => setValue(x, () => Crumb.GetParameter(0)).Return())
                .ThrowNew(typeof(NotSupportedException), "Value does not inherits from IEnumerable");
            }
            else if (propertyType.Implements(__IList.Type.Fullname) && propertyType.ParameterlessContructor != null)
            {
                var addRange = propertyType.GetMethod("AddRange", 1, false);
                if (addRange == null)
                {
                    var add   = propertyType.GetMethod("Add", 1);
                    var array = setterCode.CreateVariable(propertyType.ChildType.MakeArray());
                    setterCode.Assign(array).Set(Crumb.GetParameter(0));
                    setterCode.For(array, (x, item) => loadValue(x).Callvirt(add, item));
                    if (!add.ReturnType.IsVoid)
                    {
                        setterCode.Pop();
                    }
                }
                else
                {
                    loadValue(setterCode).Callvirt(addRange, Crumb.GetParameter(0));
                }
            }
            else if (propertyType.IsEnum)
            {
                // Enums requires special threatment
                setterCode.Load(Crumb.GetParameter(0)).Is(typeof(string)).Then(x =>
                {
                    var stringVariable = setterCode.CreateVariable(typeof(string));
                    setterCode.Assign(stringVariable).Set(Crumb.GetParameter(0));
                    setValue(setterCode, () => stringVariable).Return();
                });

                setValue(setterCode, () => Crumb.GetParameter(0));
            }
            else
            {
                setValue(setterCode, () => Crumb.GetParameter(0));
            }

            setterCode.Return().Replace();
        }