/// <summary> /// Create join point from export. /// </summary> /// <param name="instance">Instance where is export defined.</param> /// <param name="export">Export which join point is created.</param> internal JoinPoint(ComponentRef instance, Export export) { Point = export; Contract = export.Contract; ContractType = export.ExportType; Instance = instance; }
private bool noInitializedCandidatesError(ComponentRef component, Import import, IEnumerable <ComponentRef> candidatesInProgress) { var importPoint = component.GetPoint(import); string error = "Can't satisfy import"; if (candidatesInProgress.Any()) { error += ", there are circular dependencies in prerequisity imports"; foreach (var candidate in candidatesInProgress) { makeErrorJoins(importPoint, candidate, "Can't get export because of unsatisfied prerequisities"); } } else { error = noMatchingExportError(importPoint, error); } //set error to import setError(importPoint, error); if (import.IsPrerequisity) { setWarning(component.ExportPoints, "Because of unsatisfied prerequisity import, exports cannot be provided"); } return(false); }
/// <summary> /// Can be satisfied only after Prerequisities imports has been satisfied /// </summary> /// <param name="inst"></param> /// <returns></returns> private bool satisfyNormImports(ComponentRef inst) { if (!inst.HasSatisfiedPreImports) { throw new NotSupportedException("InternalError:Cant satisfy imports before prerequisities are satisfied"); } foreach (var import in inst.Imports) { if (import.IsPrerequisity) { //satisfy only normal imports, because prerequisities has to be satisfied now continue; } if (!satisfyImport(inst, import)) { //composition failed return(false); } } inst.IsSatisfied = true; return(true); }
private bool satisfyFromCandidates(ComponentRef component, Import import, IEnumerable <ComponentRef> candidates) { var importPoint = component.GetPoint(import); foreach (var candidate in candidates) { if (!satisfyPreImports(candidate)) { setError(importPoint, "Cannot satisfy import, because depending component cannot be instantiated"); makeErrorJoins(importPoint, candidate, "This export cannot be provided before prerequisity imports are satisfied"); //satisfy all needed requirments return(false); } if (!satisfyImport(component, import, candidate)) { //errors were set return(false); } } if (!import.IsPrerequisity) { // else it will be set via importing constructor setImport(importPoint); } return(true); }
/// <summary> /// Satisfy given import. Found exports are added int storage /// </summary> /// <param name="component"></param> /// <param name="import"></param> /// <returns></returns> bool satisfyImport(ComponentRef component, Import import) { if (import.IsPrerequisity && component.IsConstructed) { //instance is already constructed - dont need satisfy via importing constructor return(true); } var candidates = getExportCandidates(import); //determine that import has any candidates //(even those, that cannot be used for import because of missing initialization) //filter candidates that are initialized now (circular dependency) var initializedCandidates = candidates.Except(_currentPrereqInstances); var candidatesInProgress = candidates.Intersect(_currentPrereqInstances); var hasInitializedCandidates = initializedCandidates.Any(); if (!hasInitializedCandidates && !import.AllowDefault) { return(noInitializedCandidatesError(component, import, candidatesInProgress)); } if (initializedCandidates.Count() > 1 && !import.AllowMany) { return(tooManyCandidatesError(component, import, initializedCandidates)); } return(satisfyFromCandidates(component, import, initializedCandidates)); }
/// <summary> /// Prerequisity imports has to be satisfied before component construction /// </summary> /// <param name="inst"></param> /// <returns></returns> private bool satisfyPreImports(ComponentRef inst) { if (inst.IsConstructed) { return(true); } if (inst.ComposingFailed) { //has been already proceeded return(false); } if (_currentPrereqInstances.Contains(inst)) { //circular dependency return(false); } var preImports = new List <ComponentRef>(); bool satisfied = true; _currentPrereqInstances.Add(inst); //avoid dependency cycling foreach (var import in inst.Imports) { if (!import.IsPrerequisity) { //satisfy only prerequisities continue; } if (satisfyImport(inst, import)) { //import was satisfied continue; } satisfied = false; break; } _currentPrereqInstances.Remove(inst); if (!satisfied) { return(false); } if (!constructInstance(inst)) { return(false); } inst.HasSatisfiedPreImports = true; return(true); }
private bool tooManyCandidatesError(ComponentRef component, Import import, IEnumerable <ComponentRef> candidates) { var importPoint = component.GetPoint(import); setError(importPoint, "There are more than one matching component for export satisfiyng"); foreach (var expProvider in candidates) { makeErrorJoins(importPoint, expProvider, "Matching export in ambiguous component"); } return(false); }
/// <summary> /// enqueue call importing/default constructor on instance /// </summary> /// <param name="inst"></param> private bool constructInstance(ComponentRef inst) { if (!inst.HasImportingConstructor) { setError(inst.ExportPoints, "Cannot provide exports because of missing importing or parameter less constructor"); setError(inst.ImportPoints, "Cannot set imports, because of missing importing or parameter less constructor"); _failed = true; return(false); } callImportingConstructor(inst); return(true); }
/// <summary> /// Add component which will be available at given component reference. /// </summary> /// <param name="component">The component.</param> /// <param name="componentRef">The component reference.</param> private void addInputComponent(Instance component, ComponentRef componentRef) { var argumentIndex = _inputInstances.Count; _inputInstances.Add(component); var storage = string.Format("$arg_{0}", argumentIndex); emit((e) => e.AssignArgument(storage, component.Info, (uint)argumentIndex)); _instanceStorages.Add(componentRef, storage); _componentRefs.Add(componentRef); }
private void callImportingConstructor(ComponentRef component) { var args = new List <InstanceRef>(); foreach (var import in component.Imports) { if (import.Setter == null) //has to be satisfied via importing constructor { var imp = component.GetPoint(import); args.Add(createExport(imp)); } } component.Construct(component.ComponentInfo.ImportingConstructor, args.ToArray()); }
/// <summary> /// make error joins between matching exports (used for showing errors) /// </summary> /// <param name="imp"></param> /// <param name="exportProvider"></param> /// <param name="expWarning"></param> private void makeErrorJoins(JoinPoint imp, ComponentRef exportProvider, string expWarning) { var exps = new List <JoinPoint>(); foreach (var exp in exportProvider.ExportPoints) { if (!match(imp.Point as Import, exp)) { continue; } exps.Add(exp); } makeErrorJoins(imp, exps, expWarning); }
/// <summary> /// Adds the constructed components to the context. /// </summary> /// <param name="components">The constructed components.</param> internal void AddConstructedComponents(IEnumerable <Instance> components) { if (components == null) { return; } foreach (var component in components) { var info = _services.GetComponentInfo(component.Info); var componentRef = new ComponentRef(this, true, info, component); addInputComponent(component, componentRef); } }
/// <summary> /// Create join point from import. /// </summary> /// <param name="instance">Instance where is import defined.</param> /// <param name="import">Import which join point is created.</param> internal JoinPoint(ComponentRef instance, Import import) { IsPrerequesity = import.IsPrerequisity; Point = import; Contract = import.Contract; AllowDefault = import.AllowDefault; AllowMany = import.AllowMany; var info = import.ImportTypeInfo; ContractType = info.ImportType; ImportItemType = info.ItemType; Instance = instance; }
private bool satisfyComponent(ComponentRef inst) { if (inst.IsSatisfied) { //instance has already been satisfied return(true); } if (inst.ComposingFailed) { //instance has been proceeded, but failed return(false); } var satisfied = satisfyPreImports(inst) && satisfyNormImports(inst); return(satisfied); }
/// <summary> /// find exports which satisfies import from exportsProvider (exportsProvider has been instatiated and its exports has to match into import) /// found exports are added into storage /// /// provide type checking of join, on fail set errors and return false /// </summary> /// <param name="component"></param> /// <param name="import"></param> /// <param name="exportsProvider"></param> private bool satisfyImport(ComponentRef component, Import import, ComponentRef exportsProvider) { Debug.Assert(exportsProvider.IsConstructed, "candidate has to be constructed before providing exports"); var importPoint = component.GetPoint(import); foreach (var exportPoint in exportsProvider.ExportPoints) { if (match(import, exportPoint)) { var join = new Join(importPoint, exportPoint); _joins.Add(join); if (!typeCheck(join)) { return(false); } _storage.Add(importPoint, exportPoint); } } return(true); }