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();
        }
Exemplo n.º 3
0
        public void ImplementBamlInitializer(Builder builder)
        {
            var xamlList = builder.ResourceNames?.Where(x => x.EndsWith(".baml")).Select(x => x.Replace(".baml", ".xaml")).ToArray();

            if (!this.IsActivatorReferenced || !this.IsXAML || xamlList == null || xamlList.Length == 0 || !builder.TypeExists("System.Windows.Application"))
            {
                return;
            }

            using (new StopwatchLog(this, "xaml/baml resources"))
            {
                this.Log($"Checking for xaml/baml resources without initializers.");

                var application        = new __Application();
                var extensions         = new __Extensions();
                var resourceDictionary = new __ResourceDictionary();
                var collection         = new __ICollection_1();
                var uri = new __Uri();

                this.Log($"Implementing XAML initializer for baml resources.");

                // First we have to find every InitializeComponent method so that we can remove bamls that are already initialized.
                var allInitializeComponentMethods = builder.FindMethodsByName(SearchContext.Module, "InitializeComponent", 0).Where(x => !x.IsAbstract);
                var ldStrs = new ConcurrentBag <string>();

                Parallel.ForEach(allInitializeComponentMethods, methods =>
                {
                    foreach (var str in methods.GetLoadStrings())
                    {
                        ldStrs.Add(str);
                    }
                });

                var xamlWithInitializers         = ldStrs.Select(x => x.Substring(x.IndexOf("component/") + "component/".Length)).ToArray();
                var xamlThatRequiredInitializers = xamlList
                                                   .Where(x => !xamlWithInitializers.Contains(x))
                                                   .Select(x =>
                {
                    var index = uint.MaxValue;
                    if (x.IndexOf('-') > 0)
                    {
                        var dashPosition  = x.LastIndexOf('-') + 1;
                        var pointPosition = x.IndexOf('.', dashPosition);

                        if (uint.TryParse(x.Substring(dashPosition, pointPosition > dashPosition ? pointPosition - dashPosition : x.Length - dashPosition), out uint result))
                        {
                            index = result;
                        }
                    }

                    return(new { Index = index, Item = x });
                })
                                                   .OrderBy(x => x.Index)
                                                   .ThenBy(x => x.Item)
                                                   .ToArray();

                var resourceDictionaryMergerClass = builder.CreateType("XamlGeneratedNamespace", TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed, "<>_generated_resourceDictionary_Loader");
                resourceDictionaryMergerClass.CustomAttributes.Add(__ComponentAttribute.Type, __ResourceDictionary.Type.Fullname);
                resourceDictionaryMergerClass.CustomAttributes.AddEditorBrowsableAttribute(EditorBrowsableState.Never);
                resourceDictionaryMergerClass.CustomAttributes.AddCompilerGeneratedAttribute();

                //var method = resourceDictionaryMergerClass.CreateMethod(Modifiers.Private, "AddToDictionary", typeof(string));
                resourceDictionaryMergerClass.CreateConstructor().NewCode().Context(x =>
                {
                    var resourceDick = x.CreateVariable(__ICollection_1.Type.MakeGeneric(__ResourceDictionary.Type));
                    x.Call(
                        x.NewCode().Call(x.NewCode().Call(application.Current) /* Instance */, application.Resources) /* Instance */, resourceDictionary.MergedDictionaries)
                    .StoreLocal(resourceDick);

                    var resourceDictionaryInstance = x.CreateVariable(__ResourceDictionary.Type);

                    foreach (var item in xamlThatRequiredInitializers)
                    {
                        this.Log($"- Adding XAML '{item.Item}' with index '{item.Index}' to the Application's MergeDictionary");
                        x.NewObj(resourceDictionary.Ctor).StoreLocal(resourceDictionaryInstance);
                        x.Call(resourceDictionaryInstance, resourceDictionary.SetSource,
                               x.NewCode().NewObj(uri.Ctor, $"pack://application:,,,/{Path.GetFileNameWithoutExtension(this.Builder.Name)};component/{item.Item}")); // TODO -Need modification for UWP)
                        x.Call(resourceDick, collection.Add.MakeGeneric(__ResourceDictionary.Type), resourceDictionaryInstance);
                    }
                })
                .Return()
                .Replace();

                // Let us look for ResourceDictionaries without a InitializeComponent in their ctor
                // TODO

                resourceDictionaryMergerClass.ParameterlessContructor.CustomAttributes.AddEditorBrowsableAttribute(EditorBrowsableState.Never);
                resourceDictionaryMergerClass.ParameterlessContructor.CustomAttributes.Add(__ComponentConstructorAttribute.Type);
            }
        }
Exemplo n.º 4
0
        public void ImplementBamlInitializer(Builder builder)
        {
            this.LogInfo($"Checking for xaml/baml resources without initializers.");

            var xamlList = builder.ResourceNames?.Where(x => x.EndsWith(".baml")).Select(x => x.Replace(".baml", ".xaml")).ToArray();

            if (xamlList == null || xamlList.Length == 0 || !builder.TypeExists("System.Windows.Application"))
            {
                return;
            }

            var application        = new __Application(builder);
            var extensions         = new __Extensions(builder);
            var resourceDictionary = new __ResourceDictionary(builder);
            var collection         = new __ICollection_1(builder);

            this.LogInfo($"Implementing XAML initializer for baml resources.");

            // First we have to find every InitializeComponent method so that we can remove bamls that are already initialized.
            var allInitializeComponentMethods = builder.FindMethodsByName(SearchContext.Module, "InitializeComponent", 0).Where(x => !x.IsAbstract);
            var ldStrs = new ConcurrentBag <string>();

            Parallel.ForEach(allInitializeComponentMethods, methods =>
            {
                foreach (var str in methods.GetLoadStrings())
                {
                    ldStrs.Add(str);
                }
            });

            var xamlWithInitializers         = ldStrs.Select(x => x.Substring(x.IndexOf("component/") + "component/".Length)).ToArray();
            var xamlThatRequiredInitializers = xamlList.Where(x => !xamlWithInitializers.Contains(x));

            var resourceDictionaryMergerClass = builder.CreateType("XamlGeneratedNamespace", TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed, "<>_generated_resourceDictionary_Loader");

            resourceDictionaryMergerClass.CustomAttributes.Add(builder.GetType("Cauldron.Activator.ComponentAttribute"), resourceDictionary.Type.Fullname);
            resourceDictionaryMergerClass.CustomAttributes.AddEditorBrowsableAttribute(EditorBrowsableState.Never);
            resourceDictionaryMergerClass.CustomAttributes.AddCompilerGeneratedAttribute();

            //var method = resourceDictionaryMergerClass.CreateMethod(Modifiers.Private, "AddToDictionary", typeof(string));
            resourceDictionaryMergerClass.CreateConstructor().NewCode().Context(x =>
            {
                x.Load(x.This).Call(builder.GetType(typeof(object)).Import().ParameterlessContructor.Import());

                var resourceDick = x.CreateVariable(collection.Type.MakeGeneric(resourceDictionary.Type));
                x.Call(
                    x.NewCode().Call(x.NewCode().Call(application.Current) /* Instance */, application.Resources) /* Instance */, resourceDictionary.MergedDictionaries)
                .StoreLocal(resourceDick);

                var resourceDictionaryInstance = x.CreateVariable(resourceDictionary.Type);

                foreach (var item in xamlThatRequiredInitializers)
                {
                    x.NewObj(resourceDictionary.Ctor).StoreLocal(resourceDictionaryInstance);
                    x.Call(resourceDick, collection.Add.MakeGeneric(resourceDictionary.Type), resourceDictionaryInstance);
                    x.Call(resourceDictionaryInstance, resourceDictionary.SetSource,
                           x.NewCode().Call(extensions.RelativeUri, $"/{Path.GetFileNameWithoutExtension(this.Builder.Name)};component/{item}")); // TODO -Need modification for UWP)
                }
            })
            .Return()
            .Replace();

            resourceDictionaryMergerClass.ParameterlessContructor.CustomAttributes.AddEditorBrowsableAttribute(EditorBrowsableState.Never);
            resourceDictionaryMergerClass.ParameterlessContructor.CustomAttributes.Add(builder.GetType("Cauldron.Activator.ComponentConstructorAttribute"));
        }