Ejemplo n.º 1
0
 public static IOperation GenerateAutoMergeOperation <T, TProperty, TMergeKey>(this T _this, string propertyName, TProperty newValue, TProperty oldValue, TMergeKey mergeKey, TimeSpan timeSpan)
 {
     return(new MergeableOperation <TProperty>(
                x => { FastReflection.SetProperty(_this, propertyName, x); },
                newValue,
                oldValue, new ThrottleMergeJudge <TMergeKey>(mergeKey, timeSpan)));
 }
Ejemplo n.º 2
0
        public void FastReflectionPropertiesStatic()
        {
            var fastReflection = new FastReflection();

            fastReflection.SetStaticProperty(typeof(MockValue), nameof(MockValue.StaticFoo), 123);
            Assert.AreEqual(123, fastReflection.GetStaticPropertyOrEnum(typeof(MockValue), nameof(MockValue.StaticFoo)));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AssemblySandbox"/> class.
        /// </summary>
        public AssemblySandbox()
        {
            _appDomain = AppDomainManager.CreateUniqueAppDomain();

            _assemblyManager = CreateInstanceMarshalByRefObject <AssemblyManager>(Logger.Instance, Localization.LocalizationHelper.GetCurrentCulture());
            Reflection       = CreateInstanceMarshalByRefObject <FastReflection>(this);
        }
        protected object ParseList(Type listType, XContainer node, string rootNodeName, string childNodeName)
        {
            if (!listType.IsGenericType)
            {
                return(null);
            }

            if (!node.Descendants(rootNodeName).Any())
            {
                return(null);
            }

            Type objType = listType.GetGenericArguments().First();

            var childNodes = node.Descendants(rootNodeName).First().Descendants(childNodeName);
            var count      = childNodes.Count();

            if (count > 0)
            {
                var rtn = ObjectCreator.Create(listType, Type.EmptyTypes, null);
                foreach (var childNode in childNodes)
                {
                    object obj = ParseNode(objType, childNode);
                    FastReflection.AddObjectToList(rtn, obj);
                }
                return(rtn);
            }
            else
            {
                return(null);
            }
        }
Ejemplo n.º 5
0
        public async Task FastReflectionEvents()
        {
            var fastReflection = new FastReflection();
            var testValue      = new MockValue();

            var action = new Action(() =>
            {
                eventRaiseCount++;
            });

            fastReflection.SubscribeEvent(testValue, nameof(MockValue.MockEventChanged), action);

            await Task.Delay(200);

            testValue.RaiseEvent();
            await Task.Delay(200);

            fastReflection.Dispose();

            await Task.Delay(200);

            testValue.RaiseEvent();
            await Task.Delay(200);

            Assert.AreEqual(1, eventRaiseCount);
        }
        public static IMergeableOperation ToOperation <T, TProperty>(this T @this, Expression <Func <T, TProperty> > selector)
        {
            var propertyName = selector.GetMemberName();
            var currentValue = FastReflection.GetProperty <TProperty>(@this, propertyName);

            return(GenerateSetPropertyOperation(@this, propertyName, currentValue, Operation.DefaultMergeSpan));
        }
Ejemplo n.º 7
0
        protected override List <TRow> GetItems()
        {
            var items = base.GetItems();

            if (items.Any())
            {
                var attr = items.First().GetType().GetCustomAttribute <LocalizationRowAttribute>();
                if (attr == null)
                {
                    return(items);
                }

                var localRowType        = attr.LocalizationRow;
                var localRowFactory     = FastReflection.DelegateForConstructor <Row>(localRowType);
                var localRow            = localRowFactory();
                var foreignKeyFieldName = attr.MappedIdField ?? ((Field)((IIdRow)items.First()).IdField).PropertyName;
                var foreignKeyField     = localRow.FindFieldByPropertyName(foreignKeyFieldName) ??
                                          localRow.FindField(foreignKeyFieldName);
                var foreignKeyCriteria = new Criteria(foreignKeyField.PropertyName ?? foreignKeyField.Name);

                var languageIdKeyField = ((Field)((ILocalizationRow)localRow).CultureIdField).PropertyName;
                var languageIdField    = localRow.FindFieldByPropertyName(languageIdKeyField) ??
                                         localRow.FindField(languageIdKeyField);
                var languageIdCriteria = new Criteria(languageIdField.PropertyName ?? languageIdField.Name);

                var culture = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;

                var userLanguage = new LanguageRow();
                using (var connectionLanguage = SqlConnections.NewFor <LanguageRow>())
                {
                    userLanguage = connectionLanguage.TryFirst <LanguageRow>(new Criteria(LanguageRow.Fields.LanguageId).Like($"%{culture}%"));
                    if (userLanguage == null)
                    {
                        return(items);
                    }
                }

                var listHandler = DefaultHandlerFactory.ListHandlerFor(localRowType);
                var listRequest = DefaultHandlerFactory.ListRequestFor(localRowType);
                listRequest.ColumnSelection = ColumnSelection.List;
                listRequest.Criteria        = (foreignKeyCriteria.In(items.Select(i => i.IdField[i])) && languageIdCriteria == userLanguage.Id.Value);

                var translationsResponse = listHandler.Process(SqlConnections.NewFor <TRow>(), listRequest);
                if (translationsResponse.Entities.Count == 0)
                {
                    return(items);
                }
                foreach (var item in items)
                {
                    var translated = translationsResponse.Entities.Cast <IOMPLocalizationLangRow>().FirstOrDefault(
                        t => (Int32)foreignKeyField.AsObject(t as Row) == item.IdField[item]);
                    if (translated != null && !string.IsNullOrEmpty(translated.NameField[translated as Row]))
                    {
                        item.NameField[item] = translated.NameField[translated as Row];
                    }
                }
            }

            return(items);
        }
Ejemplo n.º 8
0
        public void FastReflectionProperties()
        {
            var fastReflection = new FastReflection();
            var testValue      = new MockValue();

            Assert.AreEqual(1, fastReflection.GetProperty(testValue, nameof(MockValue.Foo)));
            Assert.AreEqual(2, fastReflection.GetProperty(testValue, nameof(MockValue.Bar)));



            try
            {
                fastReflection.GetProperty(testValue, nameof(MockValue.Boo));
                Assert.Fail();
            }
            catch (MemberAccessException)
            {
            }
            catch
            {
                Assert.Fail();
            }



            try
            {
                fastReflection.GetProperty(testValue, "Buzz");
                Assert.Fail();
            }
            catch (MemberAccessException)
            {
            }
            catch
            {
                Assert.Fail();
            }


            testValue = new MockValue();
            fastReflection.SetProperty(testValue, nameof(MockValue.Foo), 123);
            Assert.AreEqual(123, fastReflection.GetProperty(testValue, nameof(MockValue.Foo)));



            try
            {
                fastReflection.SetProperty(testValue, nameof(MockValue.Bar), 123);
                Assert.Fail();
            }
            catch (MemberAccessException)
            {
            }
            catch
            {
                Assert.Fail();
            }
        }
Ejemplo n.º 9
0
 /// <summary>
 /// 初始化一个新 <see cref="OracleProvider" /> 实例。
 /// </summary>
 /// <exception cref="System.InvalidOperationException">Can't find Connection type:  + _connectionTypeName</exception>
 public OracleProvider()
 {
     //_connectionType = TypeFromAssembly(_connectionTypeName, _assemblyName);
     //_commandType = TypeFromAssembly(_commandTypeName, _assemblyName);
     _connectionType = FastReflection.FastGetType(_connectionTypeName);
     _commandType    = FastReflection.FastGetType(_commandTypeName);
     if (_connectionType == null)
     {
         throw new InvalidOperationException("Can't find Connection type: " + _connectionTypeName);
     }
 }
Ejemplo n.º 10
0
        public void FastReflectionInstantiate()
        {
            var fastReflection = new FastReflection();

            var instance1 = fastReflection.Instantiate(typeof(StringBuilder));

            Assert.IsInstanceOfType(instance1, typeof(StringBuilder));

            var instance3 = (string)fastReflection.Instantiate(typeof(string));

            Assert.IsInstanceOfType(instance3, typeof(string));

            var instance4 = (bool)fastReflection.Instantiate(typeof(bool));

            Assert.IsInstanceOfType(instance4, typeof(bool));

            var instance2 = (MockValue)fastReflection.Instantiate(typeof(MockValue));

            Assert.AreEqual(1, instance2.Foo);

            instance2 = (MockValue)fastReflection.Instantiate(typeof(MockValue), 123);
            instance2 = (MockValue)fastReflection.Instantiate(typeof(MockValue), 456);
            instance2 = (MockValue)fastReflection.Instantiate(typeof(MockValue), 789);
            Assert.AreEqual(789, instance2.Foo);

            instance2 = (MockValue)fastReflection.Instantiate(typeof(MockValue), "100");
            Assert.AreEqual(1000, instance2.Foo);

            try
            {
                fastReflection.Instantiate(typeof(MockValue), 1, 2, 3);
                Assert.Fail();
            }
            catch (TypeLoadException)
            {
            }
            catch
            {
                Assert.Fail();
            }

            try
            {
                fastReflection.Instantiate(typeof(MockValue), true);
                Assert.Fail();
            }
            catch (TypeLoadException)
            {
            }
            catch
            {
                Assert.Fail();
            }
        }
        public object Field(object obj, string fieldName)
        {
            if (obj == null)
            {
                return(null);
            }

            if (obj is DataObject)
            {
                return(((DataObject)obj)[fieldName]);
            }

            return(FastReflection.GetValue(obj, fieldName));
        }
Ejemplo n.º 12
0
        private TEventHandler GetHandler(Action <TEventArgs> onNext)
        {
            TEventHandler handler;

            if (_conversion is null)
            {
                handler = FastReflection.CreateDelegate <TEventHandler>(onNext, typeof(Action <TEventArgs>).GetMethod(nameof(Action <TEventArgs> .Invoke)));
            }
            else
            {
                handler = _conversion(onNext);
            }

            return(handler);
        }
Ejemplo n.º 13
0
        private TEventHandler GetHandler(Action <EventPattern <TEventArgs> > onNext)
        {
            TEventHandler handler;

            if (_conversion == null)
            {
                Action <object, TEventArgs> h = (sender, eventArgs) => onNext(new EventPattern <TEventArgs>(sender, eventArgs));
                handler = FastReflection.CreateDelegate <TEventHandler>(h, typeof(Action <object, TEventArgs>).GetMethod(nameof(Action <object, TEventArgs> .Invoke)));
            }
            else
            {
                handler = _conversion((sender, eventArgs) => onNext(new EventPattern <TEventArgs>(sender, eventArgs)));
            }

            return(handler);
        }
        public void Add(Type contract, FastReflection.IDynamicConstructor ctor)
        {
            contract.ThrowIfNull("contract", "Parameter cannot be null.");
            ctor.ThrowIfNull("ctor", "Parameter cannot be null.");

            if (_ctorContainer.ContainsKey(contract))
            {
                _ctorContainer[contract].Add(ctor);
            }
            else
            {
                SafeCollection<FastReflection.IDynamicConstructor> collection = new SafeCollection<FastReflection.IDynamicConstructor>();
                collection.Add(ctor);
                _ctorContainer.TryAdd(contract, collection);
            }
        }
Ejemplo n.º 15
0
        public bool ActivateFor(Row row)
        {
            var loc = row as IOMPLocalizationRow;

            if (loc == null)
            {
                return(false);
            }

            attr = row.GetType().GetCustomAttribute <LocalizationRowAttribute>();
            if (attr == null)
            {
                return(false);
            }

            localRowType = attr.LocalizationRow;
            if (!typeof(ILocalizationRow).IsAssignableFrom(localRowType))
            {
                throw new ArgumentException(String.Format(
                                                "Row type '{0}' has a LocalizationRowAttribute, " +
                                                "but its localization row type ('{1}') doesn't implement ILocalizationRow interface!",
                                                row.GetType().FullName, localRowType.FullName));
            }

            localRowFactory = FastReflection.DelegateForConstructor <Row>(localRowType);
            var localRow = localRowFactory();

            var foreignKeyFieldName = attr.MappedIdField ?? ((Field)((IIdRow)row).IdField).PropertyName;

            foreignKeyField = localRow.FindFieldByPropertyName(foreignKeyFieldName) ??
                              localRow.FindField(foreignKeyFieldName);

            this.foreignKeyCriteria = new Criteria(foreignKeyField.PropertyName ?? foreignKeyField.Name);


            var languageIdKeyField = ((Field)((ILocalizationRow)localRow).CultureIdField).PropertyName;

            languageIdField = localRow.FindFieldByPropertyName(languageIdKeyField) ??
                              localRow.FindField(languageIdKeyField);

            this.languageIdCriteria = new Criteria(languageIdField.PropertyName ?? languageIdField.Name);

            return(true);
        }
Ejemplo n.º 16
0
        public void FastReflectionEnum()
        {
            var fastReflection = new FastReflection();

            Assert.AreEqual(System.IO.FileMode.CreateNew, fastReflection.GetStaticPropertyOrEnum(typeof(System.IO.FileMode), nameof(System.IO.FileMode.CreateNew)));

            try
            {
                fastReflection.GetStaticPropertyOrEnum(typeof(System.IO.FileMode), "Hello");
                Assert.Fail();
            }
            catch (ArgumentException)
            {
            }
            catch (Exception)
            {
                Assert.Fail();
            }
        }
Ejemplo n.º 17
0
        public IPropertyBuilder Register <T>(string propertyName)
        {
            if (FastReflection.ExistsSetter(Object, propertyName) is false)
            {
                RegisterReadOnly(() => FastReflection.GetProperty <T>(Object, propertyName));
            }
            else
            {
                Register(
                    () => FastReflection.GetProperty <T>(Object, propertyName),
                    (x) =>
                {
                    FastReflection.SetProperty(Object, propertyName, x);
                });
            }

            _properties[_properties.Count - 1].Name = propertyName;

            return(this);
        }
Ejemplo n.º 18
0
        public void FastReflectionMethods()
        {
            var fastReflection = new FastReflection();
            var testValue      = new MockValue();

            Assert.IsNull(fastReflection.InvokeMethod(testValue, nameof(MockValue.VoidMethod)));
            fastReflection.InvokeMethod(testValue, nameof(MockValue.VoidMethod)); // Must call from the cache

            Assert.AreEqual(246, fastReflection.InvokeMethod(testValue, nameof(MockValue.ReturnMethod), 123));



            try
            {
                fastReflection.InvokeMethod(testValue, nameof(MockValue.ReturnMethod), "Bad argument");
                Assert.Fail();
            }
            catch (TypeLoadException)
            {
            }
            catch
            {
                Assert.Fail();
            }



            try
            {
                fastReflection.InvokeMethod(testValue, nameof(MockValue.ReturnMethod), "Bad argument", "Second bad argument");
                Assert.Fail();
            }
            catch (TypeLoadException)
            {
            }
            catch
            {
                Assert.Fail();
            }
        }
        public static IDisposable BindPropertyChanged <T>(this IOperationController controller, INotifyPropertyChanged owner, string propertyName, bool autoMerge = true)
        {
            var prevValue         = FastReflection.GetProperty <T>(owner, propertyName);
            var callFromOperation = false;

            owner.PropertyChanged += PropertyChanged;

            return(new Disposer(() => owner.PropertyChanged -= PropertyChanged));

            // local function
            void PropertyChanged(object sender, PropertyChangedEventArgs args)
            {
                if (callFromOperation)
                {
                    return;
                }

                if (args.PropertyName == propertyName)
                {
                    callFromOperation = true;
                    T   newValue  = FastReflection.GetProperty <T>(owner, propertyName);
                    var operation = owner
                                    .GenerateAutoMergeOperation(propertyName, newValue, prevValue, $"{sender.GetHashCode()}.{propertyName}", Operation.DefaultMergeSpan);

                    if (autoMerge)
                    {
                        operation = operation.Merge(controller);
                    }

                    operation
                    .AddPreEvent(() => callFromOperation  = true)
                    .AddPostEvent(() => callFromOperation = false);

                    prevValue = newValue;

                    controller.Push(operation);
                    callFromOperation = false;
                }
            }
        }
Ejemplo n.º 20
0
        public void FastReflectionMethodsStatic()
        {
            var fastReflection = new FastReflection();

            var instance = "123";
            var result   = fastReflection.InvokeStaticMethod(typeof(int), nameof(int.Parse), instance);

            Assert.AreEqual(123, result);

            try
            {
                fastReflection.InvokeStaticMethod(typeof(MockValue), nameof(MockValue.VoidMethod));
                Assert.Fail();
            }
            catch (NullReferenceException)
            {
            }
            catch
            {
                Assert.Fail();
            }
        }
Ejemplo n.º 21
0
        private static List <PropertyData> GetProperties(Type type)
        {
            var properties = new List <PropertyData>();

            foreach (PropertyInfo propertyInfo in type.GetProperties())
            {
                PacketIndexAttribute packetIndexAttribute = propertyInfo.GetCustomAttribute <PacketIndexAttribute>();
                if (packetIndexAttribute == null)
                {
                    continue;
                }

                properties.Add(new PropertyData
                {
                    PropertyType         = propertyInfo.PropertyType,
                    PacketIndexAttribute = packetIndexAttribute,
                    Setter = FastReflection.GetPropertySetter(type, propertyInfo),
                    Getter = FastReflection.GetPropertyGetter(type, propertyInfo)
                });
            }

            return(properties);
        }
Ejemplo n.º 22
0
        public bool ActivateFor(Row row)
        {
            if (ReferenceEquals(null, Target))
            {
                return(false);
            }

            attr = Target.GetAttribute <LinkingSetRelationAttribute>();
            if (attr == null)
            {
                return(false);
            }

            if (!(row is IIdRow))
            {
                throw new ArgumentException(String.Format("Field '{0}' in row type '{1}' has a LinkingSetRelationBehavior " +
                                                          "but it doesn't implement IIdRow!",
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }


            var listType = Target.ValueType;

            if (!listType.IsGenericType ||
                listType.GetGenericTypeDefinition() != typeof(List <>))
            {
                throw new ArgumentException(String.Format("Field '{0}' in row type '{1}' has a LinkingSetRelationBehavior " +
                                                          "but its property type is not a generic List (e.g. List<int>)!",
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            var rowType = attr.RowType;

            if (rowType.IsAbstract ||
                !typeof(Row).IsAssignableFrom(rowType))
            {
                throw new ArgumentException(String.Format(
                                                "Field '{0}' in row type '{1}' has a LinkingSetRelationBehavior " +
                                                "but specified row type is not valid row class!",
                                                Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            if (!typeof(IIdRow).IsAssignableFrom(rowType))
            {
                throw new ArgumentException(String.Format(
                                                "Field '{0}' in row type '{1}' has a LinkingSetRelationBehavior " +
                                                "but specified row type doesn't implement IIdRow!",
                                                Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            listFactory = FastReflection.DelegateForConstructor <IList>(listType);
            rowFactory  = FastReflection.DelegateForConstructor <Row>(rowType);

            listHandlerFactory = FastReflection.DelegateForConstructor <IListRequestProcessor>(
                typeof(ListRequestHandler <>).MakeGenericType(rowType));

            saveHandlerFactory = FastReflection.DelegateForConstructor <ISaveRequestProcessor>(
                typeof(SaveRequestHandler <>).MakeGenericType(rowType));

            saveRequestFactory = FastReflection.DelegateForConstructor <ISaveRequest>(
                typeof(SaveRequest <>).MakeGenericType(rowType));

            deleteHandlerFactory = FastReflection.DelegateForConstructor <IDeleteRequestProcessor>(
                typeof(DeleteRequestHandler <>).MakeGenericType(rowType));

            var detailRow = rowFactory();

            thisKeyField = detailRow.FindFieldByPropertyName(attr.ThisKey) ??
                           detailRow.FindField(attr.ThisKey);

            if (ReferenceEquals(thisKeyField, null))
            {
                throw new ArgumentException(String.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                          "This field is specified for a linking set relation in field '{2}' of row type '{3}'.",
                                                          attr.ThisKey, detailRow.GetType().FullName,
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            itemKeyField = detailRow.FindFieldByPropertyName(attr.ItemKey) ??
                           detailRow.FindField(attr.ItemKey);

            if (ReferenceEquals(itemKeyField, null))
            {
                throw new ArgumentException(String.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                          "This field is specified for a linking set relation in field '{2}' of row type '{3}'.",
                                                          attr.ItemKey, detailRow.GetType().FullName,
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            return(true);
        }
Ejemplo n.º 23
0
        public bool ActivateFor(Row row)
        {
            var attrs = row.GetType().GetCustomAttributes <UpdatableExtensionAttribute>();

            if (attrs == null || !attrs.Any())
            {
                return(false);
            }

            var sourceByExpression = row.GetFields().ToLookup(x =>
                                                              BracketLocator.ReplaceBrackets(x.Expression.TrimToEmpty(), BracketRemoverDialect.Instance));

            this.infoList = attrs.Select(attr =>
            {
                var info  = new RelationInfo();
                info.Attr = attr;

                var rowType = attr.RowType;
                if (rowType.IsAbstract ||
                    !typeof(Row).IsAssignableFrom(rowType))
                {
                    throw new ArgumentException(String.Format(
                                                    "Row type '{1}' has an ExtensionRelation attribute " +
                                                    "but its specified extension row type '{0}' is not a valid row class!",
                                                    rowType.FullName,
                                                    row.GetType().FullName));
                }

                info.RowFactory = FastReflection.DelegateForConstructor <Row>(rowType);

                info.ListHandlerFactory = FastReflection.DelegateForConstructor <IListRequestProcessor>(
                    typeof(ListRequestHandler <>).MakeGenericType(rowType));

                info.SaveHandlerFactory = FastReflection.DelegateForConstructor <ISaveRequestProcessor>(
                    typeof(SaveRequestHandler <>).MakeGenericType(rowType));

                info.SaveRequestFactory = FastReflection.DelegateForConstructor <ISaveRequest>(
                    typeof(SaveRequest <>).MakeGenericType(rowType));

                info.DeleteHandlerFactory = FastReflection.DelegateForConstructor <IDeleteRequestProcessor>(
                    typeof(DeleteRequestHandler <>).MakeGenericType(rowType));

                var thisKey = attr.ThisKey;
                if (string.IsNullOrEmpty(thisKey))
                {
                    if (!(row is IIdRow))
                    {
                        throw new ArgumentException(String.Format(
                                                        "Row type '{0}' has an ExtensionRelation attribute " +
                                                        "but its ThisKey is not specified!",
                                                        row.GetType().FullName));
                    }

                    info.ThisKeyField = (Field)(((IIdRow)row).IdField);
                }
                else
                {
                    info.ThisKeyField = row.FindFieldByPropertyName(attr.ThisKey) ?? row.FindField(attr.ThisKey);
                    if (ReferenceEquals(info.ThisKeyField, null))
                    {
                        throw new ArgumentException(String.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                                  "This field is specified for an ExtensionRelation attribute",
                                                                  attr.ThisKey,
                                                                  row.GetType().FullName));
                    }
                }

                var ext = info.RowFactory();

                var otherKey = attr.OtherKey;
                if (string.IsNullOrEmpty(otherKey))
                {
                    info.OtherKeyField = ext.FindField(info.ThisKeyField.Name);

                    if (ReferenceEquals(info.OtherKeyField, null) && ext is IIdRow)
                    {
                        info.OtherKeyField = (Field)(((IIdRow)row).IdField);
                    }

                    if (ReferenceEquals(info.OtherKeyField, null))
                    {
                        throw new ArgumentException(String.Format(
                                                        "Row type '{1}' has an ExtensionRelation attribute " +
                                                        "but its OtherKey is not specified!",
                                                        row.GetType().FullName));
                    }
                }
                else
                {
                    info.OtherKeyField = ext.FindFieldByPropertyName(attr.OtherKey) ?? ext.FindField(attr.OtherKey);
                    if (ReferenceEquals(info.OtherKeyField, null))
                    {
                        throw new ArgumentException(String.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                                  "This field is specified for an ExtensionRelation attribute on '{2}'",
                                                                  attr.OtherKey,
                                                                  ext.GetType().FullName,
                                                                  row.GetType().FullName));
                    }
                }

                if (!string.IsNullOrEmpty(attr.FilterField))
                {
                    info.FilterField = ext.FindFieldByPropertyName(attr.FilterField) ?? ext.FindField(attr.FilterField);
                    if (ReferenceEquals(info.FilterField, null))
                    {
                        throw new ArgumentException(String.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                                  "This field is specified as FilterField for an ExtensionRelation attribute on '{2}'",
                                                                  attr.OtherKey,
                                                                  ext.GetType().FullName,
                                                                  row.GetType().FullName));
                    }

                    info.FilterValue = info.FilterField.ConvertValue(attr.FilterValue, CultureInfo.InvariantCulture);
                }

                if (!string.IsNullOrEmpty(attr.PresenceField))
                {
                    info.PresenceField = ext.FindFieldByPropertyName(attr.PresenceField) ?? ext.FindField(attr.PresenceField);
                    if (ReferenceEquals(info.PresenceField, null))
                    {
                        throw new ArgumentException(String.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                                  "This field is specified as PresenceField as an ExtensionRelation attribute.",
                                                                  attr.PresenceField,
                                                                  row.GetType().FullName));
                    }

                    info.PresenceValue = attr.PresenceValue;
                }

                var extFields   = ext.GetFields();
                var alias       = attr.Alias;
                var aliasPrefix = attr.Alias + "_";

                var joinByKey = new HashSet <string>(extFields.Joins.Keys, StringComparer.OrdinalIgnoreCase);

                Func <string, string> mapAlias = x =>
                {
                    if (x == "t0" || x == "T0")
                    {
                        return(alias);
                    }

                    if (!joinByKey.Contains(x))
                    {
                        return(x);
                    }

                    return(aliasPrefix + x);
                };

                Func <string, string> mapExpression = x =>
                {
                    if (x == null)
                    {
                        return(null);
                    }

                    return(JoinAliasLocator.ReplaceAliases(x, mapAlias));
                };

                info.Mappings = new List <Tuple <Field, Field> >();
                foreach (var field in extFields)
                {
                    if (ReferenceEquals(info.OtherKeyField, field))
                    {
                        continue;
                    }

                    if (ReferenceEquals(info.FilterField, field))
                    {
                        continue;
                    }

                    var expression = field.Expression.TrimToEmpty();

                    if (string.IsNullOrEmpty(expression))
                    {
                        continue;
                    }

                    expression = mapExpression(expression);
                    expression = BracketLocator.ReplaceBrackets(expression,
                                                                BracketRemoverDialect.Instance);

                    var match = sourceByExpression[expression].FirstOrDefault();
                    if (ReferenceEquals(null, match))
                    {
                        continue;
                    }

                    if (match.IsTableField())
                    {
                        continue;
                    }

                    if (ReferenceEquals(info.ThisKeyField, match))
                    {
                        continue;
                    }

                    if (field.GetType() != match.GetType())
                    {
                        throw new ArgumentException(String.Format(
                                                        "Row type '{0}' has an ExtensionRelation attribute to '{1}'." +
                                                        "Their '{2}' and '{3}' fields are matched but they have different types ({4} and {5})!",
                                                        row.GetType().FullName,
                                                        ext.GetType().FullName,
                                                        field.PropertyName ?? field.Name,
                                                        match.PropertyName ?? match.Name,
                                                        field.GetType().Name,
                                                        match.GetType().Name));
                    }

                    info.Mappings.Add(new Tuple <Field, Field>(match, field));
                }

                if (info.Mappings.Count == 0)
                {
                    throw new ArgumentException(String.Format(
                                                    "Row type '{0}' has an ExtensionRelation attribute " +
                                                    "but no view fields could be matched to extension row '{1}'!",
                                                    row.GetType().FullName,
                                                    ext.GetType().FullName));
                }

                return(info);
            }).ToList();

            return(true);
        }
Ejemplo n.º 24
0
        public bool ActivateFor(Row row)
        {
            if (ReferenceEquals(null, Target))
                return false;

            attr = Target.GetAttribute<MasterDetailRelationAttribute>();
            if (attr == null)
                return false;

            var rowListType = Target.ValueType;
            if (!rowListType.IsGenericType ||
                rowListType.GetGenericTypeDefinition() != typeof(List<>))
            {
                throw new ArgumentException(String.Format("Field '{0}' in row type '{1}' has a MasterDetailRelationAttribute " +
                    "but its property type is not a generic List (e.g. List<Row>)!",
                    Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            var rowType = rowListType.GetGenericArguments()[0];
            if (rowType.IsAbstract ||
                !typeof(Row).IsAssignableFrom(rowType))
            {
                throw new ArgumentException(String.Format(
                    "Field '{0}' in row type '{1}' has a MasterDetailRelationAttribute " +
                    "but its property type is not a generic list of rows (e.g. List<Row>)!",
                        Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            rowListFactory = FastReflection.DelegateForConstructor<IList>(rowListType);
            rowFactory = FastReflection.DelegateForConstructor<Row>(rowType);

            listHandlerFactory = FastReflection.DelegateForConstructor<IListRequestProcessor>(
                typeof(ListRequestHandler<>).MakeGenericType(rowType));

            saveHandlerFactory = FastReflection.DelegateForConstructor<ISaveRequestProcessor>(
                typeof(SaveRequestHandler<>).MakeGenericType(rowType));

            saveRequestFactory = FastReflection.DelegateForConstructor<ISaveRequest>(
                typeof(SaveRequest<>).MakeGenericType(rowType));

            deleteHandlerFactory = FastReflection.DelegateForConstructor<IDeleteRequestProcessor>(
                typeof(DeleteRequestHandler<>).MakeGenericType(rowType));

            if (attr.MasterKeyField != null)
            {
                // Use field from AltIdField
                masterKeyField = row.FindFieldByPropertyName(attr.MasterKeyField) ??
                    row.FindField(attr.MasterKeyField);
                if (ReferenceEquals(masterKeyField, null))
                    throw new ArgumentException(String.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                        "This field is specified for a master detail relation in field '{2}'.",
                        attr.MasterKeyField, row.GetType().FullName,
                        Target.PropertyName ?? Target.Name));
            }
            else
            {
                // Default behaviour: use id field
                masterKeyField = (Field)((row as IIdRow).IdField);
            }

            var detailRow = rowFactory();
            foreignKeyField = detailRow.FindFieldByPropertyName(attr.ForeignKey) ??
                detailRow.FindField(attr.ForeignKey);

            if (ReferenceEquals(foreignKeyField, null))
                throw new ArgumentException(String.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                    "This field is specified for a master detail relation in field '{2}' of row type '{3}'.",
                    attr.ForeignKey, detailRow.GetType().FullName,
                    Target.PropertyName ?? Target.Name, row.GetType().FullName));

            this.foreignKeyCriteria = new Criteria(foreignKeyField.PropertyName ?? foreignKeyField.Name);

            if (!string.IsNullOrEmpty(attr.FilterField))
            {
                this.filterField = detailRow.FindFieldByPropertyName(attr.FilterField) ?? detailRow.FindField(attr.FilterField);
                if (ReferenceEquals(null, this.filterField))
                    throw new ArgumentException(String.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                        "This field is specified for a master detail relation as FilterField in field '{2}' of row type '{3}'.",
                        attr.FilterField, detailRow.GetType().FullName,
                        Target.PropertyName ?? Target.Name, row.GetType().FullName));

                this.filterCriteria = new Criteria(filterField.PropertyName ?? filterField.Name);
                this.filterValue = filterField.ConvertValue(attr.FilterValue, CultureInfo.InvariantCulture);
                if (this.filterValue == null)
                {
                    this.filterCriteria = this.filterCriteria.IsNull();
                    this.queryCriteria = this.filterField.IsNull();
                }
                else
                {
                    this.filterCriteria = this.filterCriteria == new ValueCriteria(this.filterValue);
                    this.queryCriteria = this.filterField == new ValueCriteria(this.filterValue);
                }
            }

            queryCriteria = queryCriteria & ServiceQueryHelper.GetNotDeletedCriteria(detailRow);

            this.includeColumns = new HashSet<string>();

            if (!string.IsNullOrEmpty(attr.IncludeColumns))
                foreach (var s in attr.IncludeColumns.Split(','))
                {
                    var col = s.TrimToNull();
                    if (col != null)
                        this.includeColumns.Add(col);
                }

            return true;
        }
Ejemplo n.º 25
0
        public bool ActivateFor(Row row)
        {
            if (ReferenceEquals(null, Target))
            {
                return(false);
            }

            attr = Target.GetAttribute <MasterDetailRelationAttribute>();
            if (attr == null)
            {
                return(false);
            }

            var rowListType = Target.ValueType;

            if (!rowListType.IsGenericType ||
                rowListType.GetGenericTypeDefinition() != typeof(List <>))
            {
                throw new ArgumentException(String.Format("Field '{0}' in row type '{1}' has a MasterDetailRelationAttribute " +
                                                          "but its property type is not a generic List (e.g. List<Row>)!",
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            var rowType = rowListType.GetGenericArguments()[0];

            if (rowType.IsAbstract ||
                !typeof(Row).IsAssignableFrom(rowType))
            {
                throw new ArgumentException(String.Format(
                                                "Field '{0}' in row type '{1}' has a MasterDetailRelationAttribute " +
                                                "but its property type is not a generic list of rows (e.g. List<Row>)!",
                                                Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            rowListFactory = FastReflection.DelegateForConstructor <IList>(rowListType);
            rowFactory     = FastReflection.DelegateForConstructor <Row>(rowType);

            listHandlerFactory = FastReflection.DelegateForConstructor <IListRequestProcessor>(
                typeof(ListRequestHandler <>).MakeGenericType(rowType));

            saveHandlerFactory = FastReflection.DelegateForConstructor <ISaveRequestProcessor>(
                typeof(SaveRequestHandler <>).MakeGenericType(rowType));

            saveRequestFactory = FastReflection.DelegateForConstructor <ISaveRequest>(
                typeof(SaveRequest <>).MakeGenericType(rowType));

            deleteHandlerFactory = FastReflection.DelegateForConstructor <IDeleteRequestProcessor>(
                typeof(DeleteRequestHandler <>).MakeGenericType(rowType));

            var detailRow = rowFactory();

            foreignKeyField = detailRow.FindFieldByPropertyName(attr.ForeignKey) ??
                              detailRow.FindField(attr.ForeignKey);

            if (ReferenceEquals(foreignKeyField, null))
            {
                throw new ArgumentException(String.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                          "This field is specified for a master detail relation in field '{2}' of row type '{3}'.",
                                                          attr.ForeignKey, detailRow.GetType().FullName,
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            return(true);
        }
        protected T ParseNode <T>(XContainer node)
            where T : new()
        {
            var properties = typeof(T).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);

            T rtn = ObjectCreator <T> .Instance.Create(Type.EmptyTypes, null);

            foreach (var property in properties)
            {
                if (property.PropertyType.IsGenericType)
                {
                    XmlParseInfoAttribute parseInfo = XmlParseInfoAttribute.GetAttribute(property);
                    if (parseInfo == null)
                    {
                        throw new Exception(string.Format("{1}.{0}未定义XmlParseInfoAttribute", property.Name, property.DeclaringType.Name));
                    }
                    else
                    {
                        var value = ParseList(property.PropertyType, node, parseInfo.NodeName, parseInfo.ChildNodeName);
                        FastReflection.SetPropertyValue <object>(rtn, property, value);
                    }
                }
                else
                {
                    string valueStr = ReadValueStr(node, property.Name);
                    if (!string.IsNullOrEmpty(valueStr))
                    {
                        if (property.PropertyType == typeof(string))
                        {
                            FastReflection <T> .SetPropertyValue <string>(rtn, property, valueStr);
                        }
                        else if (property.PropertyType == typeof(Int32))
                        {
                            int value = DataHelper.TryParseInt32(valueStr);
                            FastReflection <T> .SetPropertyValue <Int32>(rtn, property, value);
                        }
                        else if (property.PropertyType == typeof(Int64))
                        {
                            Int64 value = DataHelper.TryParseInt64(valueStr);
                            FastReflection <T> .SetPropertyValue <Int64>(rtn, property, value);
                        }
                        else if (property.PropertyType == typeof(Double))
                        {
                            Double value = DataHelper.TryParseDouble(valueStr);
                            FastReflection <T> .SetPropertyValue <Double>(rtn, property, value);
                        }
                        else if (property.PropertyType == typeof(Decimal))
                        {
                            Decimal value = DataHelper.TryParseDecimal(valueStr);
                            FastReflection <T> .SetPropertyValue <Decimal>(rtn, property, value);
                        }
                        else if (property.PropertyType == typeof(Boolean))
                        {
                            Boolean value = DataHelper.TryParseBoolean(valueStr);
                            FastReflection <T> .SetPropertyValue <Boolean>(rtn, property, value);
                        }
                        else if (property.PropertyType.IsEnum)
                        {
                            int value = DataHelper.TryParseInt32(valueStr);

                            if (Enum.IsDefined(property.PropertyType, value))
                            {
                                FastReflection <T> .SetPropertyValue <object>(rtn, property, value);
                            }
                        }
                    }
                }
            }
            return(rtn);
        }
        protected object ParseNode(Type returnType, XContainer node)
        {
            if (returnType.IsEnum)
            {
                string valueStr = (node as XElement).Value;
                int    value    = 0;
                if (!string.IsNullOrEmpty(valueStr))
                {
                    value = DataHelper.TryParseInt32(valueStr);
                }
                return(value);
            }
            else
            {
                var properties = returnType.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);

                object rtn = ObjectCreator.Create(returnType, Type.EmptyTypes, null);

                foreach (var property in properties)
                {
                    string valueStr = ReadValueStr(node, property.Name);
                    if (!string.IsNullOrEmpty(valueStr))
                    {
                        if (property.PropertyType == typeof(string))
                        {
                            FastReflection.SetPropertyValue <string>(rtn, property, valueStr);
                        }
                        else if (property.PropertyType == typeof(Int32))
                        {
                            int value = DataHelper.TryParseInt32(valueStr);
                            FastReflection.SetPropertyValue <Int32>(rtn, property, value);
                        }
                        else if (property.PropertyType == typeof(Int64))
                        {
                            Int64 value = DataHelper.TryParseInt64(valueStr);
                            FastReflection.SetPropertyValue <Int64>(rtn, property, value);
                        }
                        else if (property.PropertyType == typeof(Double))
                        {
                            Double value = DataHelper.TryParseDouble(valueStr);
                            FastReflection.SetPropertyValue <Double>(rtn, property, value);
                        }
                        else if (property.PropertyType == typeof(Decimal))
                        {
                            Decimal value = DataHelper.TryParseDecimal(valueStr);
                            FastReflection.SetPropertyValue <Decimal>(rtn, property, value);
                        }
                        else if (property.PropertyType == typeof(Boolean))
                        {
                            Boolean value = DataHelper.TryParseBoolean(valueStr);
                            FastReflection.SetPropertyValue <Boolean>(rtn, property, value);
                        }
                        else if (property.PropertyType.IsEnum)
                        {
                            int value = DataHelper.TryParseInt32(valueStr);

                            if (Enum.IsDefined(property.PropertyType, value))
                            {
                                FastReflection.SetPropertyValue <object>(rtn, property, value);
                            }
                        }
                    }
                    else if (property.PropertyType.IsGenericType)
                    {
                        XmlParseInfoAttribute parseInfo = XmlParseInfoAttribute.GetAttribute(property);
                        var value = ParseList(property.PropertyType, node, parseInfo.NodeName, parseInfo.ChildNodeName);
                        FastReflection.SetPropertyValue <object>(rtn, property, value);
                    }
                }
                return(rtn);
            }
        }
Ejemplo n.º 28
0
        public static IOperation GenerateSetOperation <T, TProperty>(this T _this, string propertyName, TProperty newValue)
        {
            var oldValue = (TProperty)FastReflection.GetProperty(_this, propertyName);

            return(GenerateAutoMergeOperation(_this, propertyName, newValue, oldValue, $"{_this.GetHashCode()}.{propertyName}"));
        }
Ejemplo n.º 29
0
        public bool ActivateFor(Row row)
        {
            attr = row.GetType().GetCustomAttribute <LocalizationRowAttribute>();
            if (attr == null)
            {
                return(false);
            }

            localRowType = attr.LocalizationRow;
            if (!typeof(ILocalizationRow).IsAssignableFrom(localRowType))
            {
                throw new ArgumentException(String.Format(
                                                "Row type '{0}' has a LocalizationRowAttribute, " +
                                                "but its localization row type ('{1}') doesn't implement ILocalizationRow interface!",
                                                row.GetType().FullName, localRowType.FullName));
            }

            if (!typeof(IIdRow).IsAssignableFrom(localRowType))
            {
                throw new ArgumentException(String.Format(
                                                "Row type '{0}' has a LocalizationRowAttribute, " +
                                                "but its localization row type ('{1}') doesn't implement IIdRow interface!",
                                                row.GetType().FullName, localRowType.FullName));
            }

            if (!(row is IIdRow))
            {
                throw new ArgumentException(String.Format(
                                                "Row type '{0}' has a LocalizationRowAttribute, " +
                                                "but row type itself doesn't implement IIdRow interface!",
                                                row.GetType().FullName));
            }

            rowFactory      = FastReflection.DelegateForConstructor <Row>(row.GetType());
            localRowFactory = FastReflection.DelegateForConstructor <Row>(localRowType);

            var localRow = localRowFactory();

            localRowInstance = localRow;

            rowPrefixLength      = PrefixHelper.DeterminePrefixLength(row.EnumerateTableFields(), x => x.Name);
            localRowPrefixLength = PrefixHelper.DeterminePrefixLength(localRow.EnumerateTableFields(), x => x.Name);
            localRowIdField      = (Field)(((IIdRow)localRow).IdField);
            cultureIdField       = ((ILocalizationRow)localRow).CultureIdField;

            var foreignKeyFieldName = attr.MappedIdField ?? ((Field)((IIdRow)row).IdField).PropertyName;

            foreignKeyField = localRow.FindFieldByPropertyName(foreignKeyFieldName) ??
                              localRow.FindField(foreignKeyFieldName);

            if (ReferenceEquals(null, foreignKeyField))
            {
                throw new ArgumentException(String.Format(
                                                "Row type '{0}' has a LocalizationRowAttribute, " +
                                                "but its localization row type ('{1}') doesn't have a field with name '{2}'!",
                                                row.GetType().FullName, localRowType.FullName, foreignKeyFieldName));
            }

            dictionaryFactory = FastReflection.DelegateForConstructor <IDictionary>(
                typeof(Dictionary <,>).MakeGenericType(typeof(string), row.GetType()));

            this.foreignKeyCriteria = new Criteria(foreignKeyField.PropertyName ?? foreignKeyField.Name);
            return(true);
        }
        public bool ActivateFor(Row row)
        {
            if (ReferenceEquals(null, Target))
            {
                return(false);
            }

            attr = Target.GetAttribute <LinkingSetRelationAttribute>();
            if (attr == null)
            {
                return(false);
            }

            if (!(row is IIdRow))
            {
                throw new ArgumentException(String.Format("Field '{0}' in row type '{1}' has a LinkingSetRelationBehavior " +
                                                          "but it doesn't implement IIdRow!",
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }


            var listType = Target.ValueType;

            if (!listType.IsGenericType ||
                listType.GetGenericTypeDefinition() != typeof(List <>))
            {
                throw new ArgumentException(String.Format("Field '{0}' in row type '{1}' has a LinkingSetRelationBehavior " +
                                                          "but its property type is not a generic List (e.g. List<int>)!",
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            rowType = attr.RowType;
            if (rowType.IsAbstract ||
                !typeof(Row).IsAssignableFrom(rowType))
            {
                throw new ArgumentException(String.Format(
                                                "Field '{0}' in row type '{1}' has a LinkingSetRelationBehavior " +
                                                "but specified row type is not valid row class!",
                                                Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            if (!typeof(IIdRow).IsAssignableFrom(rowType))
            {
                throw new ArgumentException(String.Format(
                                                "Field '{0}' in row type '{1}' has a LinkingSetRelationBehavior " +
                                                "but specified row type doesn't implement IIdRow!",
                                                Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            listFactory = FastReflection.DelegateForConstructor <IList>(listType);
            rowFactory  = FastReflection.DelegateForConstructor <Row>(rowType);

            var detailRow = rowFactory();

            thisKeyField = detailRow.FindFieldByPropertyName(attr.ThisKey) ??
                           detailRow.FindField(attr.ThisKey);

            if (ReferenceEquals(thisKeyField, null))
            {
                throw new ArgumentException(String.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                          "This field is specified for a linking set relation in field '{2}' of row type '{3}'.",
                                                          attr.ThisKey, detailRow.GetType().FullName,
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            this.thisKeyCriteria = new Criteria(thisKeyField.PropertyName ?? thisKeyField.Name);

            itemKeyField = detailRow.FindFieldByPropertyName(attr.ItemKey) ??
                           detailRow.FindField(attr.ItemKey);

            if (ReferenceEquals(itemKeyField, null))
            {
                throw new ArgumentException(String.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                          "This field is specified for a linking set relation in field '{2}' of row type '{3}'.",
                                                          attr.ItemKey, detailRow.GetType().FullName,
                                                          Target.PropertyName ?? Target.Name, row.GetType().FullName));
            }

            if (!string.IsNullOrEmpty(attr.FilterField))
            {
                this.filterField = detailRow.FindFieldByPropertyName(attr.FilterField) ?? detailRow.FindField(attr.FilterField);
                if (ReferenceEquals(null, this.filterField))
                {
                    throw new ArgumentException(String.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                              "This field is specified for a linking set relation as FilterField in field '{2}' of row type '{3}'.",
                                                              attr.FilterField, detailRow.GetType().FullName,
                                                              Target.PropertyName ?? Target.Name, row.GetType().FullName));
                }

                this.filterCriteria = new Criteria(filterField.PropertyName ?? filterField.Name);
                this.filterValue    = filterField.ConvertValue(attr.FilterValue, CultureInfo.InvariantCulture);
                if (this.filterValue == null)
                {
                    this.filterCriteria = this.filterCriteria.IsNull();
                    this.queryCriteria  = this.filterField.IsNull();
                }
                else
                {
                    this.filterCriteria = this.filterCriteria == new ValueCriteria(this.filterValue);
                    this.queryCriteria  = this.filterField == new ValueCriteria(this.filterValue);
                }
            }

            queryCriteria = queryCriteria & ServiceQueryHelper.GetNotDeletedCriteria(detailRow);

            return(true);
        }
Ejemplo n.º 31
0
        /// <summary>
        /// Parse a BaZic code and returns a syntax tree representation of the algorithm.
        /// </summary>
        /// <param name="tokens">The BaZic code represented by tokens to analyze.</param>
        /// <param name="xamlCode">The XAML code to analyze that represents the user interface.</param>
        /// <param name="resourceFilePaths">Paths to the resources files (like PNG or JPG) required for the XAML code.</param>
        /// <param name="optimize">(optional) Defines whether the generated syntax tree must be optimized for the interpreter or not.</param>
        /// <returns>A <see cref="BaZicProgram"/> that represents the syntax tree that corresponds to the input code.</returns>
        public ParserResult Parse(List <Token> tokens, string xamlCode, IEnumerable <string> resourceFilePaths = null, bool optimize = false)
        {
            Requires.NotNull(tokens, nameof(tokens));

            _issues.Clear();
            BaZicProgram program = null;

            if (tokens.Count == 0)
            {
                return(new ParserResult(program, new AggregateException(_issues)));
            }

            ThreadHelper.RunOnStaThread(() =>
            {
                try
                {
                    _reflectionHelper = new FastReflection();

                    // Parse BaZic user interface code (XAML).
                    _parsedXamlRoot = ParseXaml(xamlCode);

                    // Parse BaZic code.
                    _catchIndicator  = 0;
                    _doLoopIndicator = 0;
                    _tokenStack.Clear();

                    for (var i = tokens.Count - 1; i >= 0; i--)
                    {
                        _tokenStack.Push(tokens[i]);
                    }

                    if (_tokenStack.Peek().TokenType != TokenType.StartCode)
                    {
                        AddIssue(new BaZicParserException(L.BaZic.Parser.FormattedBadFirstToken(TokenType.StartCode)));
                    }

                    if (_tokenStack.Count <= 2)
                    {
                        if (_parsedXamlRoot == null)
                        {
                            program = new BaZicProgram();
                        }
                        else
                        {
                            ValidateResources(resourceFilePaths);

                            var uiProgram  = new BaZicUiProgram();
                            uiProgram.Xaml = xamlCode;
                            if (resourceFilePaths != null)
                            {
                                uiProgram.WithResourceFilePaths(resourceFilePaths.ToArray());
                            }
                            program = uiProgram;
                        }
                    }
                    else
                    {
                        PreviousToken = _tokenStack.Pop();
                        CurrentToken  = _tokenStack.Pop();
                        NextToken     = _tokenStack.Pop();

                        program = ParseProgram(xamlCode, resourceFilePaths);
                    }

                    if (optimize && _issues.OfType <BaZicParserException>().Count(issue => issue.Level == BaZicParserExceptionLevel.Error) == 0)
                    {
                        var optimizer = new BaZicOptimizer();
                        program       = optimizer.Optimize(program);
                    }

                    tokens.Clear();
                }
                catch (Exception exception)
                {
                    CoreHelper.ReportException(exception);
                    _issues.Add(exception);
                }
                finally
                {
                    _expectedExpressionGroupSeparator.Clear();
                    _declaredVariables.Clear();
                    _declaredParameterDeclaration.Clear();
                    _declaredMethods.Clear();
                    _declaredEvents.Clear();
                    _controlAccessors.Clear();
                    _methodInvocations.Clear();
                    _catchIndicator  = 0;
                    _doLoopIndicator = 0;
                    if (_parsedXamlRoot != null)
                    {
                        if (_parsedXamlRoot is Window window)
                        {
                            window.Close();
                        }
                        _parsedXamlRoot = null;
                    }
                    _reflectionHelper.Dispose();
                    _reflectionHelper = null;
                }
            }, true);

            return(new ParserResult(program, new AggregateException(_issues)));
        }