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(); }