private InstanceRef getImportInstance(JoinPoint import) { var imp = import.Point as Import; var setter = imp.Setter; var setterName = Naming.GetMethodName(setter); if (setterName == null || !setterName.StartsWith(Naming.SetterPrefix)) { //cannot find setter -> cannot get getter return(null); } var getterName = Naming.GetterPrefix + setterName.Substring(Naming.SetterPrefix.Length); var instType = import.Instance.Type; var getter = _context.TryGetMethod(instType, getterName); if (getter == null) { //cannot resolve getter overload return(null); } return(import.Instance.CallWithReturn(getter.MethodID)); }
/// <summary> /// Resolve error for unsatisfiable import. Make error joins and set warnings for contract matching export. /// </summary> /// <param name="impPoint">Unsatisfiable import.</param> /// <param name="errorPrefix">Error prefix.</param> /// <returns>Return error description according to given prefix.</returns> private string noMatchingExportError(JoinPoint impPoint, string errorPrefix) { var import = impPoint.Point as Import; var exps = getExports(import); if (exps.Length == 0) { //there are no matching components/or there is problem in meta data filtering. exps = getExports(import, false); if (exps.Length == 0) { errorPrefix += " because there are no exports matching contract"; } else { errorPrefix += " because of incompatible meta data"; makeErrorJoins(impPoint, exps, "Incompatible exported metadata"); } } else { errorPrefix += " because all matching components have ambiguous exports"; makeErrorJoins(impPoint, exps, "Ambiguous export"); } return(errorPrefix); }
private bool isICollectionImport(JoinPoint import, out InstanceRef iCollectionToSet, out MethodID addMethod) { addMethod = null; iCollectionToSet = null; //Detect if import type is of ICollection var imp = import.Point as Import; var itemType = imp.ImportTypeInfo.ItemType; var collectionTypeName = string.Format("System.Collections.Generic.ICollection<{0}>", itemType.TypeName); var collectionType = TypeDescriptor.Create(collectionTypeName); var isICollection = _context.IsOfType(imp.ImportTypeInfo.ImportType, collectionType); if (!isICollection) { //cannot resolve type as ICollection return(false); } var collectionAddMethod = _context.GetMethod(collectionType, "Add").MethodID; addMethod = collectionAddMethod; iCollectionToSet = getImportInstance(import); return(true); }
/// <summary> /// Create Join object. /// </summary> /// <param name="import">Import join point.</param> /// <param name="export">Export join point.</param> public Join(JoinPoint import, JoinPoint export) { if (!(import.Point is Import) || !(export.Point is Export)) { throw new NotSupportedException("not supported join points"); } Import = import; Export = export; }
private void makeErrorJoins(JoinPoint imp, IEnumerable <JoinPoint> exps, string expWarning) { foreach (var exp in exps) { var join = new Join(imp, exp); join.IsErrorJoin = true; _joins.Add(join); setWarning(exp, expWarning); } }
private void callSetter(JoinPoint import) //call setter { var imp = import.Point as Import; var export = createExport(import); if (export != null) { import.Instance.Call(imp.Setter, export); } }
private InstanceRef callExportGetter(JoinPoint import, JoinPoint export) { var exp = export.Point as Export; var imp = import.Point as Import; var importInfo = imp.ImportTypeInfo; InstanceRef exportedInstanceRef; if (exp.Getter == null) { //self export exportedInstanceRef = export.Instance; } else { //export from getter exportedInstanceRef = export.Instance.CallWithReturn(exp.Getter); } if (!importInfo.IsItemLazy) { return(exportedInstanceRef); } //we have to create lazy export if (importInfo.MetaDataType == null) { //only wrap instance to lazy object return(_context.CallDirectWithReturn((c, args) => { //prepare exported data var exportInstance = args[0]; var lazy = new Lazy <InstanceWrap>(() => new InstanceWrap(exportInstance)); //create instance return c.Machine.CreateDirectInstance(lazy); }, exportedInstanceRef)); } //we have to include metadata also return(_context.CallDirectWithReturn((c, args) => { //prepare exported data var exportInstance = args[0]; var metaInstance = createMetaDataInstance(c, importInfo.MetaDataType, exp.Meta); var lazy = new Lazy <InstanceWrap, InstanceWrap>(() => new InstanceWrap(exportInstance), new InstanceWrap(metaInstance)); //create instance return c.Machine.CreateDirectInstance(lazy); }, exportedInstanceRef)); }
/// <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> /// enqueue setter call which satisfy import from exports /// </summary> /// <param name="import"></param> private void setImport(JoinPoint import) { var exps = _storage.Get(import); if (exps == null) { return; //allow default doesnt require setter } foreach (var exp in exps) { _joins.Add(new Join(import, exp)); } callSetter(import); }
/// <summary> /// Determine if import is matching to given export. /// </summary> /// <param name="import">Import to test.</param> /// <param name="export">Export to test.</param> /// <param name="metaDataTest">Determine if meta data should be used for filtering.</param> /// <returns>True if import can be satisfied from export.</returns> private bool match(Import import, JoinPoint export, bool metaDataTest = true) { var importMeta = import.ImportTypeInfo.MetaDataType; bool metaDataMatch = true; if (importMeta != null && metaDataTest) { var exportMeta = (export.Point as Export).Meta; metaDataMatch = testMetaData(importMeta, exportMeta); } return(import.Contract == export.Contract && metaDataMatch); }
private void setWarning(JoinPoint point, string warning) { if (point.Warning != null) { if (point.Warning.Contains(warning)) { //same warning has already been set. return; } point.Warning += "\n" + warning; } else { point.Warning = warning; } }
private void setError(JoinPoint point, string error) { _failed = true; if (point.Error != null) { if (point.Error.Contains(error)) { //same error has already been set. return; } point.Error += "\n" + error; } else { point.Error = error; } }
private InstanceRef callManyExportGetter(JoinPoint import, IEnumerable <JoinPoint> exps) { var exportValues = new List <InstanceRef>(); foreach (var exp in exps) { exportValues.Add(callExportGetter(import, exp)); } InstanceRef iCollectionToSet; MethodID addMethod; if (isICollectionImport(import, out iCollectionToSet, out addMethod)) { //import will be filled by adding instances if (iCollectionToSet == null) { //there is no collection which could be set. setError(import, "Cannot get ICollection object, for importing exports, because of missing getter."); return(null); } var arguments = new[] { iCollectionToSet }.Union(exportValues); _context.CallDirect((c, args) => fillICollection(args[0], args.Skip(1).ToArray(), import, addMethod, c), arguments.ToArray()); //there is no returned value because import is filled via add return(null); } else { //import will be filled with an array var arr = _context.CreateArray(import.ImportItemType, exportValues); if (!_context.IsOfType(import.ContractType, arr.Type)) { setError(import, "Import type cannot handle multiple exports"); return(null); } return(arr); } }
private void fillICollection(Instance importCollection, Instance[] exports, JoinPoint import, MethodID addMethod, AnalyzingContext c) { if (exports.Length == 0) { //there is nothing to export return; } //test if import can be filled if (_context.IsNull(importCollection)) { setWarning(import, "ICollection import was not initialized after component creation"); return; } //fill with exports for (var i = 0; i < exports.Length; ++i) { var export = exports[i]; c.DynamicCall(addMethod, importCollection, export); } }
/// <summary> /// Create export for given import, from exports available in storage /// Is lazy determine, if export will be wrapped into lazys /// </summary> /// <param name="imp"></param> /// <returns></returns> private InstanceRef createExport(JoinPoint imp) { var exps = _storage.Get(imp); switch (exps.Count()) { case 0: return(null); case 1: if (imp.AllowMany) { return(callManyExportGetter(imp, exps)); } else { return(callExportGetter(imp, exps.First())); } default: return(callManyExportGetter(imp, exps)); } }
private void addImport(Import import) { var point = new JoinPoint(this, import); _importPoints.Add(import, point); }
private void addExport(Export export) { var point = new JoinPoint(this, export); _exportPoints.Add(export, point); }