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