Exemplo n.º 1
0
        protected virtual void ValidateCompositeTypeModel(CompositeValidationResult result, CompositeModel compositeModel)
        {
            // TODO validate that none of fragments have abstract non-composite methods.

            if (compositeModel.PublicTypes.Any())
            {
                Type   firstType  = compositeModel.PublicTypes.First();
                Type[] gArgs      = firstType.GetGenericArguments();
                Int32  gArgsCount = gArgs.Length;
                foreach (Type cType in compositeModel.GetAllCompositeTypes())
                {
                    this.ValidateCompositeType(result, compositeModel, cType);
                }

                foreach (Type fType in compositeModel.GetAllFragmentTypes())
                {
                    this.ValidateFragmentType(result, compositeModel, fType);
                }

                foreach (Type type in compositeModel.PublicTypes)
                {
                    this.ValidateCompositeType(result, compositeModel, type);

                    Type[] typeGargs = type.GetGenericArguments();
                    Int32  typeCount = typeGargs.Length;

                    if (typeCount > 0)
                    {
                        if (type.IsGenericTypeDefinition() != firstType.IsGenericTypeDefinition() || typeGargs.Take(Math.Min(gArgsCount, typeCount)).Where((tGArg, idx) => tGArg.IsGenericParameter != gArgs[idx].IsGenericParameter).Any())
                        {
                            result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("All type interfaces must be either genericless, generic type definitions, or having all generic parameters closed.", compositeModel));
                        }
                        else
                        {
                            // TODO generic arguments constraints
                        }
                    }
                }
                if (compositeModel.PublicTypes.Count(pType => !pType
#if WINDOWS_PHONE_APP
                                                     .GetTypeInfo()
#endif
                                                     .IsInterface) > 1)
                {
                    result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Composite types must contain at most one class, but found the following classes:\n" + String.Join(", ", compositeModel.PublicTypes.Select(pType => !pType
#if WINDOWS_PHONE_APP
                                                                                                                                                                                                                                             .GetTypeInfo()
#endif
                                                                                                                                                                                                                                             .IsInterface)), compositeModel));
                }
            }
            else
            {
                result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Composite must have at least one public type", compositeModel));
            }
        }
Exemplo n.º 2
0
        protected virtual void ValidateFragmentType(CompositeValidationResult result, CompositeModel compositeModel, Type fragmentType)
        {
            if (!fragmentType
#if WINDOWS_PHONE_APP
                .GetTypeInfo()
#endif
                .IsClass)
            {
                result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Fragments must be classes; the fragment " + fragmentType + " however is not a class.", compositeModel));
            }
            else
            {
                var baseTypes = new HashSet <Type>(fragmentType.GetAllParentTypes());
                baseTypes.Remove(fragmentType);
                if (fragmentType
#if WINDOWS_PHONE_APP
                    .GetTypeInfo()
#endif
                    .IsAbstract)
                {
                    foreach (var fMethod in fragmentType.GetAllInstanceMethods())
                    {
                        if (fMethod.IsAbstract && !compositeModel.Methods.Any(cMethod => AreSameFragmentMethods(fMethod, ReflectionHelper.FindMethodImplicitlyImplementingMethod(fragmentType, cMethod.NativeInfo))))
                        {
                            result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Found abstract method " + fMethod + " in " + fragmentType + ", with no corresponding composite method.", compositeModel));
                        }
                    }
                }
                foreach (var baseType in baseTypes)
                {
                    if (baseType.IsGenericType())
                    {
                        var baseTypeGDef = baseType.GetGenericTypeDefinition();
                        if (compositeModel.GetAllCompositeTypes().Except(compositeModel.PublicTypes).SelectMany(cType => cType.GetAllParentTypes()).Any(pType => pType.GetGenericDefinitionIfGenericType().Equals(baseTypeGDef)) &&
                            baseType.GetGenericArguments().Any(gArg => gArg.IsArray || gArg.IsByRef || gArg.IsPointer))
                        {
                            result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Fragment type implements composite type with either array, by ref or pointer generic argument. This is not allowed, as fragment might not be instantiatable in cases of non-array or non-by-ref or non-pointer generic argument of composite type.", compositeModel));
                        }
                    }
                }
            }
        }
        public PublicCompositeTypeGenerationResultImpl(
            CompositeModel cModel,
            CompositeTypeModel tModel,
            EventHandler <AssemblyLoadingArgs> loadingEvt,
            IDictionary <Assembly, Assembly> assDic,
            CompositeCodeGenerationInfo codeGenerationInfo
            )
        {
            //var orderer = new TypeLoadOrderer( cModel );

            var collectionsFactory = cModel.ApplicationModel.CollectionsFactory;
            var publicTypes        = cModel
                                     .GetAllCompositeTypes()
                                     .Concat(cModel.GetAllFragmentTypes())
                                                                                                    //.OrderBy( t => t, orderer )
                                     .Where(t => cModel.ApplicationModel.AffectedAssemblies.Contains(t.GetAssembly()))
                                     .OrderBy(t => t.Equals(cModel.MainCodeGenerationType) ? 0 : 1) // Populate main code generation type first
                                     .Select(t => GetGeneratedPublicType(t, cModel, codeGenerationInfo, loadingEvt, assDic))
                                     .Distinct()
                                     .ToArray();

            var mainTypes = publicTypes.Where(iResult => iResult.IsPublicTypeMainCompositeType());

            if (!mainTypes.Any() || mainTypes.Skip(1).Any())
            {
                throw new ArgumentException((mainTypes.Any() ? "Too many" : "Too little") + " generated main types (" + String.Join(", ", mainTypes) + "), exactly one allowed.");
            }
            var mainType = mainTypes.First();

            this._compositeFactory = (CompositeFactory)mainType.GetAssembly().GetType(mainType.Name + codeGenerationInfo.CompositeFactorySuffix, true)
#if WINDOWS_PHONE_APP
                                     .GetAllInstanceConstructors().First()
#else
                                     .GetConstructors()[0]
#endif
                                     .Invoke(null);

            var fragmentTypeGenerationResults = tModel.FragmentTypeInfos.Keys
                                                //.OrderBy( t => t, orderer )
                                                .Select(t => Tuple.Create(t, GetParticipantType(t, cModel, codeGenerationInfo, loadingEvt, assDic, codeGenerationInfo.FragmentPrefix, true)))
                                                .Where(t => t.Item2 != null)
                                                .Select(t => (FragmentTypeGenerationResult) new FragmentTypeGenerationResultImpl(t.Item1, t.Item2))
                                                .ToArray();
            var concernInvocationGenerationResults = tModel.ConcernInvocationTypeInfos.Keys
                                                     //.OrderBy( t => t, orderer )
                                                     .Select(t => Tuple.Create(t, GetParticipantType(t, cModel, codeGenerationInfo, loadingEvt, assDic, codeGenerationInfo.ConcernInvocationPrefix)))
                                                     .Where(t => t.Item2 != null)
                                                     .Select(t => (TypeGenerationResult) new TypeGenerationResultImpl(t.Item2, t.Item1))
                                                     .ToArray();
            var sideEffectInvocationGenerationResults = tModel.SideEffectInvocationTypeInfos.Keys
                                                        //.OrderBy( t => t, orderer )
                                                        .Select(t => Tuple.Create(t, GetParticipantType(t, cModel, codeGenerationInfo, loadingEvt, assDic, codeGenerationInfo.SideEffectInvocationPrefix)))
                                                        .Where(t => t.Item2 != null)
                                                        .Select(t => (TypeGenerationResult) new TypeGenerationResultImpl(t.Item2, t.Item1))
                                                        .ToArray();
            var privateCompositeGenerationresults = tModel.PrivateCompositeTypeInfos.Keys
                                                    //.OrderBy( t => t, orderer )
                                                    .Select(t => Tuple.Create(t, GetParticipantType(t, cModel, codeGenerationInfo, loadingEvt, assDic, codeGenerationInfo.PrivateCompositePrefix)))
                                                    .Where(t => t.Item2 != null)
                                                    .Select(t => (TypeGenerationResult) new TypeGenerationResultImpl(t.Item2, t.Item1))
                                                    .ToArray();

            var pGArgs = collectionsFactory.NewDictionaryProxy(
                tModel.PublicCompositeGenericArguments
                .Select((gArg, idx) => Tuple.Create(gArg, idx))
                .GroupBy(tuple => tuple.Item1.DeclaringType)
                .ToDictionary(grouping => grouping.Key, grouping => collectionsFactory.NewListProxy(grouping.Select(tuple => tuple.Item2).ToList()).CQ));

            this._generatedPublicMainType = mainType;
            this._maxParamCountForCtors   = mainType
#if WINDOWS_PHONE_APP
                                            .GetAllInstanceConstructors().First()
#else
                                            .GetConstructors(BindingFlags.Instance | BindingFlags.Public)[0]
#endif
                                            .GetParameters().Length;

            this._generatedPublicTypes = collectionsFactory.NewListProxy(publicTypes.Select(
                                                                             pt => (GeneratedTypeInfo) new GeneratedTypeInfoImpl(pt))
                                                                         .ToList()).CQ;
            this._publicCompositeGenericArguments       = pGArgs.CQ;
            this._privateCompositeGenerationResults     = collectionsFactory.NewListProxyFromParams(privateCompositeGenerationresults).CQ;
            this._fragmentGenerationResults             = collectionsFactory.NewListProxyFromParams(fragmentTypeGenerationResults).CQ;
            this._concernInvocationGenerationResults    = collectionsFactory.NewListProxyFromParams(concernInvocationGenerationResults).CQ;
            this._sideEffectInvocationGenerationResults = collectionsFactory.NewListProxyFromParams(sideEffectInvocationGenerationResults).CQ;

            // Remember to remove Qi4CS assembly if present
            assDic.Remove(ReflectionHelper.QI4CS_ASSEMBLY);
        }