Пример #1
0
        public IConstructorBuilder DefineConstructor(MethodAttributes attributes, IType[] parameters)
        {
            var builder = new AsmConstructorBuilder(this, attributes, parameters);

            TypeConstructors.Add(builder);
            return(builder);
        }
Пример #2
0
        static void Main(string[] args)
        {
            //RttiWithIs.Start();
            //RttiWithAs.Start();
            //SimpleTypeofExample.Start();
            //ReflectionDemo.Start();
            //CallingMethodsUsingReflection.Start();
            TypeConstructors.Start();

            Console.ReadKey();
        }
Пример #3
0
        private IProductType Transform(IUnitOfWork uow, ProductTypeEntity typeEntity, bool full, IDictionary <long, IProductType> loadedProducts = null, IProductPartLink parentLink = null)
        {
            // Build cache if this wasn't done before
            if (loadedProducts == null)
            {
                loadedProducts = new Dictionary <long, IProductType>();
            }

            // Take converted product from dictionary if we already transformed it
            if (loadedProducts.ContainsKey(typeEntity.Id))
            {
                return(loadedProducts[typeEntity.Id]);
            }

            // Strategy to load product and its parts
            var strategy = TypeStrategies[typeEntity.TypeName];

            // Load product
            var product = TypeConstructors[typeEntity.TypeName]();

            product.Id       = typeEntity.Id;
            product.Name     = typeEntity.Name;
            product.State    = (ProductState)typeEntity.CurrentVersion.State;
            product.Identity = new ProductIdentity(typeEntity.Identifier, typeEntity.Revision);
            strategy.LoadType(typeEntity.CurrentVersion, product);

            // Don't load parts and parent for partial view
            if (full)
            {
                LoadParts(uow, typeEntity, product, loadedProducts);
            }

            // Assign instance to dictionary of loaded products
            loadedProducts[typeEntity.Id] = product;

            return(product);
        }
Пример #4
0
        public FormDefinition GetDefinition(string xml, bool freeze)
        {
            var document = XDocument.Parse(xml);

            if (document.Root == null)
            {
                throw new InvalidOperationException("Invalid XML document.");
            }

            void AddMetadata(IDictionary <string, string> dict, XElement xelement)
            {
                const int stroffset = 5; // "meta-".Length

                foreach (var attr in xelement.Attributes())
                {
                    if (attr.Name.LocalName.StartsWith("meta-", StringComparison.OrdinalIgnoreCase))
                    {
                        dict[attr.Name.LocalName.Substring(stroffset)] = attr.Value;
                    }
                }
            }

            FormElement WithMetadata(FormElement element, XElement xelement)
            {
                AddMetadata(element.Metadata, xelement);
                return(element);
            }

            ILayout Terminal(XElement element)
            {
                var         elementName = element.Name.LocalName.ToLower();
                FormElement formElement;

                switch (elementName)
                {
                case "layout":
                    return(Layout(element));

                case "input":
                case "textarea":
                case "toggle":
                case "password":
                {
                    var  typeName   = element.TryGetAttribute("type") ?? "string";
                    var  attributes = new List <Attribute>();
                    Type propertyType;
                    if (elementName == "input" && TypeConstructors.TryGetValue(typeName, out var constructor))
                    {
                        var data = constructor(new XmlConstructionContext(element));
                        propertyType = data.PropertyType;
                        attributes.AddRange(data.CustomAttributes);
                    }
                    else if (!TypeNames.TryGetValue(typeName, out propertyType))
                    {
                        throw new InvalidOperationException($"Type '{typeName}' not found.");
                    }

                    var fieldName = element.TryGetAttribute("name");
                    attributes.Add(Utilities.GetFieldAttributeFromElement(element));
                    attributes.Add(Utilities.GetBindingAttributeFromElement(element));

                    switch (elementName)
                    {
                    case "textarea":
                        attributes.Add(new MultiLineAttribute());
                        propertyType = typeof(string);
                        break;

                    case "toggle":
                        attributes.Add(new ToggleAttribute());
                        propertyType = typeof(bool);
                        break;

                    case "password":
                        attributes.Add(new PasswordAttribute());
                        propertyType = typeof(string);
                        break;
                    }

                    attributes.AddRange(Utilities.GetValidatorsFromElement(element));
                    var property     = new DynamicProperty(fieldName, propertyType, attributes.ToArray());
                    var deserializer = TryGetDeserializer(propertyType);
                    formElement = Build(property, deserializer);
                    if (formElement != null)
                    {
                        foreach (var initializer in FieldInitializers)
                        {
                            initializer.Initialize(formElement, property, deserializer);
                        }

                        formElement.LinePosition = (Position)(-1);
                    }

                    return(new FormElementLayout(WithMetadata(formElement, element)));
                }

                case "select":
                {
                    var    from = element.TryGetAttribute("from");
                    object itemsSource;
                    string typeName;
                    string displayPath;
                    string valuePath;
                    Type   propertyType = null;
                    if (!string.IsNullOrEmpty(from))
                    {
                        if (from.StartsWith("type:"))
                        {
                            var qualifiedType = from.Substring("type:".Length);
                            var nullable      = false;
                            if (qualifiedType.EndsWith("?"))
                            {
                                qualifiedType = qualifiedType.Substring(0, qualifiedType.Length - 1);
                                nullable      = true;
                            }

                            propertyType = Utilities.FindTypes(t => t.FullName == qualifiedType).FirstOrDefault();
                            itemsSource  = propertyType ?? throw new InvalidOperationException($"Could not find type '{qualifiedType}'.");

                            if (propertyType.IsValueType && nullable)
                            {
                                propertyType = typeof(Nullable <>).MakeGenericType(propertyType);
                                itemsSource  = propertyType;
                            }

                            typeName = element.TryGetAttribute("type");
                        }
                        else
                        {
                            itemsSource = from;
                            typeName    = element.TryGetAttribute("type") ?? "string";
                        }

                        displayPath = element.TryGetAttribute("displayPath");
                        valuePath   = element.TryGetAttribute("valuePath");
                    }
                    else
                    {
                        typeName    = "string";
                        displayPath = "Name";
                        valuePath   = "Value";
                        itemsSource = Utilities.GetSelectOptionsFromElement(element);
                    }

                    if (typeName != null && !TypeNames.TryGetValue(typeName, out propertyType))
                    {
                        throw new InvalidOperationException($"Type '{typeName}' not found.");
                    }

                    if (propertyType.IsValueType &&
                        element.TryGetAttribute("nullable") != null &&
                        (!propertyType.IsGenericType || propertyType.GetGenericTypeDefinition() != typeof(Nullable <>)))
                    {
                        propertyType = typeof(Nullable <>).MakeGenericType(propertyType);
                    }

                    var fieldName  = element.TryGetAttribute("name");
                    var attributes = new List <Attribute>
                    {
                        new SelectFromAttribute(itemsSource)
                        {
                            SelectionType    = Utilities.TryParse(element.TryGetAttribute("as"), SelectionType.ComboBox),
                            DisplayPath      = displayPath,
                            ValuePath        = valuePath,
                            ItemStringFormat = element.TryGetAttribute("itemStringFormat")
                        },
                        Utilities.GetFieldAttributeFromElement(element),
                        Utilities.GetBindingAttributeFromElement(element)
                    };

                    attributes.AddRange(Utilities.GetValidatorsFromElement(element));
                    var property     = new DynamicProperty(fieldName, propertyType, attributes.ToArray());
                    var deserializer = TryGetDeserializer(propertyType);
                    formElement = Build(property, deserializer);
                    if (formElement != null)
                    {
                        foreach (var initializer in FieldInitializers)
                        {
                            initializer.Initialize(formElement, property, deserializer);
                        }

                        formElement.LinePosition = (Position)(-1);
                    }

                    return(new FormElementLayout(WithMetadata(formElement, element)));
                }

                case "title":
                    formElement = new TitleAttribute(element.GetAttributeOrValue("content"))
                    {
                        Icon = element.TryGetAttribute("icon")
                    }
                    .WithBaseProperties(element)
                    .WithTextProperties(element)
                    .GetElement();
                    return(new FormElementLayout(WithMetadata(formElement, element)));

                case "heading":
                    formElement = new HeadingAttribute(element.GetAttributeOrValue("content"))
                    {
                        Icon = element.TryGetAttribute("icon")
                    }
                    .WithBaseProperties(element)
                    .WithTextProperties(element)
                    .GetElement();
                    return(new FormElementLayout(WithMetadata(formElement, element)));

                case "text":
                    formElement = new TextAttribute(element.GetAttributeOrValue("content"))
                                  .WithBaseProperties(element)
                                  .WithTextProperties(element)
                                  .GetElement();
                    return(new FormElementLayout(WithMetadata(formElement, element)));

                case "error":
                    formElement = new ErrorTextAttribute(element.GetAttributeOrValue("content"))
                                  .WithBaseProperties(element)
                                  .WithTextProperties(element)
                                  .GetElement();
                    return(new FormElementLayout(WithMetadata(formElement, element)));

                case "img":
                    formElement = new ImageAttribute(element.TryGetAttribute("src"))
                    {
                        Width  = element.TryGetAttribute("width"),
                        Height = element.TryGetAttribute("height"),
                        HorizontalAlignment = element.TryGetAttribute("align"),
                        VerticalAlignment   = element.TryGetAttribute("valign"),
                        Stretch             = element.TryGetAttribute("stretch"),
                        StretchDirection    = element.TryGetAttribute("direction")
                    }
                    .WithBaseProperties(element)
                    .GetElement();
                    return(new FormElementLayout(WithMetadata(formElement, element)));

                case "br":
                    formElement = new BreakAttribute
                    {
                        Height = element.TryGetAttribute("height")
                    }
                    .WithBaseProperties(element)
                    .GetElement();

                    return(new FormElementLayout(WithMetadata(formElement, element)));

                case "hr":
                    var hasMargin = element.TryGetAttribute("hasMargin");
                    formElement = (hasMargin != null
                            ? new DividerAttribute(bool.Parse(hasMargin))
                            : new DividerAttribute())
                                  .WithBaseProperties(element)
                                  .GetElement();

                    return(new FormElementLayout(WithMetadata(formElement, element)));

                case "action":
                    formElement = Utilities.GetAction(element)
                                  .WithBaseProperties(element)
                                  .GetElement();
                    return(new FormElementLayout(WithMetadata(formElement, element)));

                default:
                    throw new InvalidOperationException($"Unknown element '{element.Name.LocalName}'.");
                }
            }

            GridColumnLayout Column(XElement element)
            {
                var elements = element.Elements().ToList();
                var child    = elements.Count == 1
                    ? Row(elements[0])
                    : new Layout(elements.Select(Row));

                return(new GridColumnLayout(
                           child,
                           Utilities.ParseDouble(element.TryGetAttribute("width"), 1d),
                           Utilities.ParseDouble(element.TryGetAttribute("left"), 0d),
                           Utilities.ParseDouble(element.TryGetAttribute("right"), 0d)));
            }

            GridLayout Grid(XElement element)
            {
                return(new GridLayout(
                           element.Elements().Select(Column),
                           Utilities.ParseDouble(element.TryGetAttribute("top"), 0d),
                           Utilities.ParseDouble(element.TryGetAttribute("bottom"), 0d)));
            }

            InlineLayout Inline(XElement element)
            {
                return(new InlineLayout(
                           element.Elements().Select(Terminal),
                           Utilities.ParseDouble(element.TryGetAttribute("top"), 0d),
                           Utilities.ParseDouble(element.TryGetAttribute("bottom"), 0d)));
            }

            ILayout Row(XElement element)
            {
                if (!string.Equals(element.Name.LocalName, "row", StringComparison.OrdinalIgnoreCase))
                {
                    return(Terminal(element));
                }

                if (element
                    .Elements()
                    .All(e => string.Equals(e.Name.LocalName, "col", StringComparison.OrdinalIgnoreCase)))
                {
                    return(Grid(element));
                }

                return(Inline(element));
            }

            Layout Layout(XElement element)
            {
                return(new Layout(
                           element.Elements().Select(Row),
                           Utilities.ParseThickness(element.TryGetAttribute("margin")),
                           Utilities.TryParse(element.TryGetAttribute("valign"), VerticalAlignment.Stretch),
                           Utilities.TryParse(element.TryGetAttribute("align"), HorizontalAlignment.Stretch),
                           Utilities.ParseNullableDouble(element.TryGetAttribute("minHeight")),
                           Utilities.ParseNullableDouble(element.TryGetAttribute("maxHeight"))));
            }

            var form = new FormDefinition(null); // null indicates dynamic type

            AddMetadata(form.Metadata, document.Root);
            form.FormRows.Add(new FormRow(true, 1)
            {
                Elements = { new FormElementContainer(0, 1, Layout(document.Root)) }
            });

            if (freeze)
            {
                form.FreezeAll();
            }

            return(form);
        }
Пример #5
0
        public IReadOnlyList <IProductType> LoadTypes(ProductQuery query)
        {
            using (var uow = Factory.Create(ContextMode.AllOff))
            {
                var baseSet       = uow.GetRepository <IProductTypeEntityRepository>().Linq;
                var productsQuery = query.IncludeDeleted ? baseSet : baseSet.Active();

                // Filter by type
                if (!string.IsNullOrEmpty(query.Type))
                {
                    if (query.ExcludeDerivedTypes)
                    {
                        productsQuery = productsQuery.Where(p => p.TypeName == query.Type);
                    }
                    else
                    {
                        var allTypes = ReflectionTool.GetPublicClasses <ProductType>(pt =>
                        {
                            // TODO: Clean this up with full name and proper type compatibility
                            var type = pt;
                            // Check if any interface matches
                            if (type.GetInterfaces().Any(inter => inter.Name == query.Type))
                            {
                                return(true);
                            }
                            // Check if type or base type matches
                            while (type != null)
                            {
                                if (type.Name == query.Type)
                                {
                                    return(true);
                                }
                                type = type.BaseType;
                            }
                            return(false);
                        }).Select(t => t.Name);
                        productsQuery = productsQuery.Where(p => allTypes.Contains(p.TypeName));
                    }
                }

                // Filter by identifier
                if (!string.IsNullOrEmpty(query.Identifier))
                {
                    var identifierMatches = Regex.Match(query.Identifier, "(?<startCard>\\*)?(?<filter>\\w*)(?<endCard>\\*)?");
                    var identifier        = identifierMatches.Groups["filter"].Value.ToLower();
                    if (identifierMatches.Groups["startCard"].Success && identifierMatches.Groups["endCard"].Success)
                    {
                        productsQuery = productsQuery.Where(p => p.Identifier.ToLower().Contains(identifier));
                    }
                    else if (identifierMatches.Groups["startCard"].Success)
                    {
                        productsQuery = productsQuery.Where(p => p.Identifier.ToLower().EndsWith(identifier));
                    }
                    else if (identifierMatches.Groups["endCard"].Success)
                    {
                        productsQuery = productsQuery.Where(p => p.Identifier.ToLower().StartsWith(identifier));
                    }
                    else
                    {
                        productsQuery = productsQuery.Where(p => p.Identifier.ToLower() == identifier);
                    }
                }

                // Filter by revision
                if (query.RevisionFilter == RevisionFilter.Latest)
                {
                    var compareSet = baseSet.Active();
                    productsQuery = productsQuery.Where(p => p.Revision == compareSet.Where(compare => compare.Identifier == p.Identifier).Max(compare => compare.Revision));
                }
                else if (query.RevisionFilter == RevisionFilter.Specific)
                {
                    productsQuery = productsQuery.Where(p => p.Revision == query.Revision);
                }

                // Filter by name
                if (!string.IsNullOrEmpty(query.Name))
                {
                    productsQuery = productsQuery.Where(p => p.Name.ToLower().Contains(query.Name.ToLower()));
                }

                // Filter by recipe
                if (query.RecipeFilter == RecipeFilter.WithRecipe)
                {
                    productsQuery = productsQuery.Where(p => p.Recipes.Any());
                }
                else if (query.RecipeFilter == RecipeFilter.WithoutRecipes)
                {
                    productsQuery = productsQuery.Where(p => p.Recipes.Count == 0);
                }

                // Apply selector
                switch (query.Selector)
                {
                case Selector.Parent:
                    productsQuery = productsQuery.SelectMany(p => p.Parents).Where(p => p.Parent.Deleted == null)
                                    .Select(link => link.Parent);
                    break;

                case Selector.Parts:
                    productsQuery = productsQuery.SelectMany(p => p.Parts).Where(p => p.Parent.Deleted == null)
                                    .Select(link => link.Child);
                    break;
                }

                // Include current version
                productsQuery = productsQuery.Include(p => p.CurrentVersion);

                // Execute the query
                var products = productsQuery.OrderBy(p => p.TypeName)
                               .ThenBy(p => p.Identifier)
                               .ThenBy(p => p.Revision).ToList();
                // TODO: Use TypeWrapper with constructor delegate and isolate basic property conversion
                return(products.Where(p => TypeConstructors.ContainsKey(p.TypeName)).Select(p =>
                {
                    var instance = TypeConstructors[p.TypeName]();
                    instance.Id = p.Id;
                    instance.Identity = new ProductIdentity(p.Identifier, p.Revision);
                    instance.Name = p.Name;
                    return instance;
                }).ToList());
            }
        }