예제 #1
0
        private TypeBindingInformationState NewTypeBindingInformation(
            CompositeValidationResultMutable vResult,
            CollectionsFactory collectionsFactory,
            CompositeModel compositeModel,
            AbstractInjectableModel injModel,
            Type nInfo,
            Type type,
            Type declaringType,
            IDictionary <Type, TypeBindingInformationState> privateComposites
            )
        {
            TypeBindingInformationState state = new TypeBindingInformationState(collectionsFactory);

            state.NativeInfo = nInfo.GetGenericDefinitionIfContainsGenericParameters();

            ListProxy <ListProxy <AbstractGenericTypeBinding> > bindings = collectionsFactory.NewListProxy <ListProxy <AbstractGenericTypeBinding> >();
            Boolean allBindingsOK = this.NewGenericTypeBinding(collectionsFactory, compositeModel, type, declaringType, bindings, privateComposites);

            if (allBindingsOK)
            {
                state.Bindings.AddRange(bindings.CQ);
            }
            else if (vResult != null)
            {
                vResult.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Failed to deduce generic bindings for " + (injModel == null ? (Object)type : injModel) + ".", compositeModel, injModel as AbstractMemberInfoModel <Object>));
            }
            return(allBindingsOK ? state : null);
        }
예제 #2
0
        protected virtual CompositeValidationResultMutable PerformValidationWithoutTypeGeneration(CompositeModel compositeModel)
        {
            var state  = new CompositeValidationResultState(compositeModel);
            var result = new CompositeValidationResultMutable(state, new CompositeValidationResultImmutable(state));

            this.CreateValidator().ValidateComposite(result, compositeModel);
            this.PostValidateModel(compositeModel, result);
            return(result);
        }
예제 #3
0
        private IDictionary <Type, TypeBindingInformationState> CreateInvocationInfos <AttributeType>(
            CompositeValidationResultMutable vResult,
            CollectionsFactory collectionsFactory,
            CompositeModel compositeModel,
            IDictionary <Type, TypeBindingInformationState> privateComposites
            )
            where AttributeType : Attribute
        {
            var injModels       = compositeModel.GetAllInjectableModelsWithInjectionScope <AttributeType>();
            var invocationTypes = injModels.GetBottomTypes(model => model.TargetType);
            var invocationInfos = new Dictionary <Type, TypeBindingInformationState>();

            foreach (var model in invocationTypes)
            {
                var actualType = model.TargetType;
                this.ModifyTypeBindingInfoDictionary(invocationInfos, this.NewTypeBindingInformation(vResult, collectionsFactory, compositeModel, model, actualType, actualType, GetBottommostDeclaringType(model), privateComposites));
            }

            return(invocationInfos);
        }
예제 #4
0
        public virtual void ValidateComposite(CompositeValidationResultMutable result, CompositeModel compositeModel)
        {
            // TODO check that all keys of the type model CompositeTypeInformations and FragmentTypeInformations are assignable from all methods of the composite model.
            this.ValidateCompositeTypeModel(result, compositeModel);

            if (compositeModel.MainCodeGenerationType == null)
            {
                result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Composite model main code generation type was null", compositeModel));
            }
            else if (!compositeModel.PublicTypes.Contains(compositeModel.MainCodeGenerationType))
            {
                result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Composite model main code generation type " + compositeModel.MainCodeGenerationType + " was not contained in its public types (" + String.Join(", ", compositeModel.PublicTypes) + ").", compositeModel));
            }
            else
            {
                CompositeMethodModel[] unimplementedMethods = compositeModel.Methods
                                                              .Where(methodModel => methodModel.Mixin == null)
                                                              .ToArray();
                if (unimplementedMethods.Any())
                {
                    foreach (CompositeMethodModel unimplementedMethod in unimplementedMethods)
                    {
                        result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("No implementation found for " + unimplementedMethod.NativeInfo + ".", compositeModel, unimplementedMethod));
                    }
                }
                else
                {
                    foreach (FieldModel fieldModel in compositeModel.Fields)
                    {
                        this.ValidateField(result, compositeModel, fieldModel);
                    }

                    foreach (ConstructorModel constructorModel in compositeModel.Constructors)
                    {
                        foreach (ParameterModel parameterModel in constructorModel.Parameters)
                        {
                            this.ValidateParameter(result, compositeModel, parameterModel);
                        }
                    }

                    foreach (CompositeMethodModel compositeMethod in compositeModel.Methods)
                    {
                        if (compositeMethod == null)
                        {
                            result.InternalValidationErrors.Add(ValidationErrorFactory.NewInternalError("Composite method model may not be null.", compositeModel));
                        }
                        else
                        {
                            this.ValidateParameter(result, compositeModel, compositeMethod.Result);
                            foreach (ParameterModel parameterModel in compositeMethod.Parameters)
                            {
                                this.ValidateParameter(result, compositeModel, parameterModel);
                            }
                            foreach (AbstractFragmentMethodModel fragmentMethod in compositeMethod.GetAllMethodModels().OfType <AbstractFragmentMethodModel>())
                            {
                                this.ValidateFragmentMethod(result, compositeModel, compositeMethod, fragmentMethod);
                            }
                            foreach (ConstraintModel constraintModel in compositeMethod.Parameters.SelectMany(param => param.Constraints).Concat(compositeMethod.Result.Constraints))
                            {
                                if (constraintModel.ConstraintType == null)
                                {
                                    result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Could not bind parameter constraint " + constraintModel.ConstraintAttribute + ".", compositeModel, compositeMethod));
                                }
                                else if (constraintModel.ConstraintType.GetConstructor(Empty <Type> .Array) == null)
                                {
                                    result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Constraints must have constructor without parameters, but constraint of type " + constraintModel.ConstraintType + " does not.", compositeModel, compositeMethod));
                                }
                                else if (constraintModel.ConstraintType.ContainsGenericParameters() && !constraintModel.ConstraintType.IsGenericTypeDefinition())
                                {
                                    result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Constraint type " + constraintModel.ConstraintType + " contains non-closed generic parameters but is not generic type definition.", compositeModel, compositeMethod));
                                }
                            }
                        }
                    }
                    foreach (var pModel in compositeModel.GetAllPropertyModels())
                    {
                        this.ValidatePropertyModel(result, compositeModel, pModel);
                    }
                    foreach (SpecialMethodModel specialMethod in compositeModel.SpecialMethods)
                    {
                        this.ValidateSpecialMethodModel(result, compositeModel, specialMethod);
                    }

                    foreach (var constraintModel in compositeModel.GetAllConstraints())
                    {
                        this.ValidateConstraintModel(result, compositeModel, constraintModel);
                    }

                    if (!result.IQ.HasAnyErrors())
                    {
                        result.TypeModel = new CompositeTypeModelImpl(compositeModel, result);
                    }
                }
            }
        }
예제 #5
0
        public CompositeTypeModelImpl(CompositeModel compositeModel, CompositeValidationResultMutable vResult)
        {
            var collectionsFactory = compositeModel.ApplicationModel.CollectionsFactory;

            this._publicCompositeGenericArguments = collectionsFactory.NewListProxy(GetCompositeModelPublicTypeGenericArguments(compositeModel).ToList()).CQ;

            var injThisTypes = compositeModel.GetAllInjectableModelsWithInjectionScope <ThisAttribute>()
                               .Select(inj => new ThisTypeInfo(inj))
                               .ToArray();
            var thisTypesInModel = compositeModel.Methods
                                   .Select(m => m.NativeInfo.DeclaringType)
                                   .Concat(compositeModel.PublicTypes)
                                   .Concat(injThisTypes.Select(inj => inj.resolvedTargetType))
                                   .Concat(compositeModel.GetAllFragmentTypes().SelectMany(ft => ft.GetAllParentTypes(false)))
                                   .GetBottomTypes();

            foreach (var injThisType in injThisTypes)
            {
                injThisType.resolvedTargetTypeFromModel = thisTypesInModel.First(tType => injThisType.resolvedTargetType.GetGenericDefinitionIfContainsGenericParameters().IsAssignableFrom_IgnoreGenericArgumentsForGenericTypes(tType));
            }

            var thisTypesToProcess = new HashSet <ThisTypeInfo>(injThisTypes.GetBottomTypes(model => model.resolvedTargetType).Distinct(INJECTABLE_MODEL_EQ_COMPARER));

            thisTypesToProcess.ExceptWith(thisTypesToProcess.Where(type => compositeModel.PublicTypes.Any(role => type.resolvedTargetType.GetGenericDefinitionIfGenericType().IsAssignableFrom_IgnoreGenericArgumentsForGenericTypes(role))).ToArray());

            // TODO check that if type binding has more than one list with indirect bindings -> throw or add error.

            var privateComposites = new Dictionary <Type, TypeBindingInformationState>();

            while (thisTypesToProcess.Any())
            {
                var processedTypes = new HashSet <ThisTypeInfo>(GDEF_EQ_COMPARER);
                foreach (var thisType in thisTypesToProcess)
                {
                    if (this.ModifyTypeBindingInfoDictionary(privateComposites, this.NewTypeBindingInformation(null, collectionsFactory, compositeModel, null, thisType.resolvedTargetTypeFromModel, thisType.resolvedTargetType, GetBottommostDeclaringType(thisType.model), privateComposites)))
                    {
                        processedTypes.Add(thisType);
                    }
                }
                thisTypesToProcess.ExceptWith(thisTypesToProcess.Where(t => processedTypes.Any(p => t.resolvedTargetType.GetGenericDefinitionIfContainsGenericParameters().Equals(p.resolvedTargetType.GetGenericDefinitionIfContainsGenericParameters()))).ToArray());
                if (processedTypes.Count == 0)
                {
                    // We are stuck
                    vResult.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("Could not deduce generic bindings for types " + String.Join(", ", thisTypesToProcess.Select(ttp => ttp.resolvedDeclaringType)), compositeModel));
                    break;
                }
                else
                {
                    processedTypes.Clear();
                }
            }

            var fragmentTypeInfos = new Dictionary <Type, TypeBindingInformationState>();

            foreach (var fragmentType in compositeModel.GetAllFragmentTypes())
            {
                // TODO check - if any parent is public or private composite type (genericdefifgenerictype), error
                if (fragmentType.IsGenericType())
                {
                    var it = FindImplementingTypeFrom(fragmentType, compositeModel.PublicTypes);
                    if (it != null || !fragmentType.ContainsGenericParameters())
                    {
                        this.ModifyTypeBindingInfoDictionary(fragmentTypeInfos, this.NewTypeBindingInformation(vResult, collectionsFactory, compositeModel, null, fragmentType, fragmentType, fragmentType, privateComposites));
                    }
                    else
                    {
                        // Private composite fragment
                        // Process all base types + injectable models of this fragment, and all their generic arguments as DFS
                        var dependentStates = Enumerable.Repeat <Tuple <Int32, TypeBindingInformationState> >(null, fragmentType.GetGenericArguments().Length).ToList();

                        foreach (var typeToProcess in fragmentType.GetAllParentTypes(false)
                                 .Concat(
                                     compositeModel.GetAllInjectableModels()
                                     .Where(inj => fragmentType.GetClassHierarchy().Contains(inj.DeclaringType))
                                     .Select(inj => inj.TargetType)
                                     ))
                        {
                            if (dependentStates.Any(item => item == null))
                            {
                                var gArgs = typeToProcess.GetGenericArguments();
                                for (var i = 0; i < gArgs.Length; ++i)
                                {
                                    foreach (var typeOrGArg in gArgs[i].AsDepthFirstEnumerable(t => t.GetGenericArgumentsSafe()))
                                    {
                                        if (typeOrGArg.IsGenericParameter && dependentStates[typeOrGArg.GenericParameterPosition] == null)
                                        {
                                            TypeBindingInformationState other;
                                            if (!privateComposites.TryGetValue(typeToProcess.GetGenericDefinitionIfContainsGenericParameters(), out other) &&
                                                compositeModel.PublicTypes.Contains(typeToProcess)
                                                )
                                            {
                                                other            = new TypeBindingInformationState(collectionsFactory);
                                                other.NativeInfo = typeToProcess;
                                            }
                                            if (other != null)
                                            {
                                                dependentStates[typeOrGArg.GenericParameterPosition] = Tuple.Create(i, other);
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                        if (!dependentStates.Any(item => item == null))
                        {
                            var state = new TypeBindingInformationState(collectionsFactory);
                            state.NativeInfo = fragmentType;
                            var max = Math.Max(1, dependentStates.Max(dState => dState.Item2.Bindings.CQ.Count));
                            if (dependentStates.Select(dState => dState.Item2.Bindings.CQ.Count).Where(c => c > 1).Distinct().Count() > 1)
                            {
                                throw new NotImplementedException("Very complex private type binding is not yet supported.");
                            }
                            else
                            {
                                for (var i = 0; i < max; ++i)
                                {
                                    state.Bindings.Add(collectionsFactory.NewListProxy(dependentStates.Select(dState =>
                                    {
                                        AbstractGenericTypeBinding gtb;
                                        if (dState.Item2.Bindings.CQ.Any())
                                        {
                                            // Private composite binding
                                            gtb = dState.Item2.Bindings.CQ[i].CQ[dState.Item1];
                                        }
                                        else
                                        {
                                            var iState = new IndirectGenericTypeBindingState();
                                            iState.GenericDefinition = dState.Item2.NativeInfo.GetGenericDefinitionIfGenericType();
                                            iState.GenericIndex      = dState.Item1;
                                            gtb = new IndirectGenericTypeBindingImpl(iState);
                                        }
                                        return(gtb);
                                    }).ToList()));
                                }
                                this.ModifyTypeBindingInfoDictionary(fragmentTypeInfos, state);
                            }
                        }
                    }
                }
                else
                {
                    var state = new TypeBindingInformationState(collectionsFactory);
                    state.NativeInfo = fragmentType;
                    this.ModifyTypeBindingInfoDictionary(fragmentTypeInfos, state);
                }
            }

            this._fragmentTypeInfos             = collectionsFactory.NewDictionaryProxy(fragmentTypeInfos.ToDictionary(kvp => kvp.Key, kvp => (TypeBindingInformation) new TypeBindingInformationImpl(kvp.Value))).CQ;
            this._concernInvocationTypeInfos    = collectionsFactory.NewDictionaryProxy(this.CreateInvocationInfos <ConcernForAttribute>(vResult, collectionsFactory, compositeModel, privateComposites).ToDictionary(kvp => kvp.Key, kvp => (TypeBindingInformation) new TypeBindingInformationImpl(kvp.Value))).CQ;
            this._sideEffectInvocationTypeInfos = collectionsFactory.NewDictionaryProxy(this.CreateInvocationInfos <SideEffectForAttribute>(vResult, collectionsFactory, compositeModel, privateComposites).ToDictionary(kvp => kvp.Key, kvp => (TypeBindingInformation) new TypeBindingInformationImpl(kvp.Value))).CQ;
            this._privateCompositeTypeInfos     = collectionsFactory.NewDictionaryProxy(privateComposites.ToDictionary(kvp => kvp.Key, kvp => (TypeBindingInformation) new TypeBindingInformationImpl(kvp.Value))).CQ;
        }