示例#1
0
    private static void CreateSetterDelegate(Builder builder, Method setterDelegateMethod, BuilderType propertyType, object value)
    {
        var setterCode = setterDelegateMethod.NewCoder();

        T CodeMe <T>(Func <Field, T> fieldCode, Func <Property, T> propertyCode) where T : class
        {
            switch (value)
            {
            case Field field: return(fieldCode(field));

            case Property property: return(propertyCode(property));

            default: return(null);
            }
        }

        if (propertyType.ParameterlessContructor != null && propertyType.ParameterlessContructor.IsPublic)
        {
            CodeMe(
                field => setterCode.If(x => x.Load(field).IsNull(), then => then.SetValue(field, x => x.NewObj(propertyType.ParameterlessContructor))),
                property => setterCode.If(x => x.Call(property.Getter).IsNull(), then => then.Call(property.Setter, x => x.NewObj(propertyType.ParameterlessContructor))));
        }

        // Only this if the property implements idisposable
        if (propertyType.Implements(typeof(IDisposable)))
        {
            CodeMe(
                field => setterCode.Call(BuilderTypes.Extensions.GetMethod_TryDisposeInternal(), x => x.Load(field)),
                property => setterCode.Call(BuilderTypes.Extensions.GetMethod_TryDisposeInternal(), x => x.Call(property.Getter)));
        }

        setterCode.If(x => x.Load(CodeBlocks.GetParameter(0)).IsNull(), then =>
        {
            // Just clear if its clearable
            if (propertyType.Implements(BuilderTypes.IList))
            {
                CodeMe(
                    field => setterCode.Load(field).Call(BuilderTypes.IList.GetMethod_Clear()).Return(),
                    property => setterCode.Call(property.Getter).Call(BuilderTypes.IList.GetMethod_Clear()).Return());
            }
            // Otherwise if the property is not a value type and nullable
            else if (!propertyType.IsValueType || propertyType.IsNullable || propertyType.IsArray)
            {
                CodeMe <CoderBase>(
                    field => setterCode.SetValue(field, null),
                    property => setterCode.Call(property.Setter, null));
            }
            else // otherwise... throw an exception
            {
                then.ThrowNew(typeof(NotSupportedException), "Value types does not accept null values.");
            }

            return(then);
        });

        setterCode.If(x => CodeMe(
                          field => x.Load(CodeBlocks.GetParameter(0)).Is(field.FieldType),
                          property => x.Load(CodeBlocks.GetParameter(0)).Is(property.ReturnType)), then =>
                      CodeMe(
                          field => then.SetValue(field, CodeBlocks.GetParameter(0)).Return(),
                          property => then.Call(property.Setter, CodeBlocks.GetParameter(0)).Return()));

        if (propertyType.Implements(BuilderTypes.IList))
        {
            var add   = propertyType.GetMethod("Add", 1);
            var array = setterDelegateMethod.GetOrCreateVariable(propertyType.ChildType.MakeArray());
            setterCode.SetValue(array, CodeBlocks.GetParameter(0));
            setterCode.For(array, (x, item, indexer) => CodeMe(
                               field => x.Load(field).Call(add, item()),
                               property => x.Call(property.Getter).Call(add, item())));
            if (!add.ReturnType.IsVoid)
            {
                setterCode.Pop();
            }
        }
        else if (propertyType.Implements(typeof(IEnumerable)) || propertyType.IsArray)
        {
            setterCode.If(x => x.Load(CodeBlocks.GetParameter(0)).Is(typeof(IEnumerable)), then =>
                          CodeMe(
                              field => then.SetValue(field, CodeBlocks.GetParameter(0)).Return(),
                              property => then.Call(property.Setter, CodeBlocks.GetParameter(0)).Return()))
            .ThrowNew(typeof(NotSupportedException), "Value does not inherits from IEnumerable");
        }
        else if (propertyType.IsEnum)
        {
            // Enums requires special threatment
            setterCode.If(x => x.Load(CodeBlocks.GetParameter(0)).Is(typeof(string)),
                          then =>
            {
                var stringVariable = setterDelegateMethod.GetOrCreateVariable(typeof(string));
                then.SetValue(stringVariable, CodeBlocks.GetParameter(0));
                CodeMe(     // Cecilator automagically implements a convertion for this
                    field => then.SetValue(field, stringVariable).Return(),
                    property => then.Call(property.Setter, stringVariable).Return());
                return(then);
            });

            CodeMe <CoderBase>(
                field => setterCode.SetValue(field, CodeBlocks.GetParameter(0)),
                property => setterCode.Call(property.Setter, CodeBlocks.GetParameter(0)));
        }
        else
        {
            CodeMe <CoderBase>(
                field => setterCode.SetValue(field, CodeBlocks.GetParameter(0)),
                property => setterCode.Call(property.Setter, CodeBlocks.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();
        }
示例#3
0
 public static bool IsIDictionary(this BuilderType builderType) => builderType.Implements(typeof(IDictionary));