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);
        }
Beispiel #4
0
 /// <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));
            }
        }
Beispiel #16
0
        private void addImport(Import import)
        {
            var point = new JoinPoint(this, import);

            _importPoints.Add(import, point);
        }
Beispiel #17
0
        private void addExport(Export export)
        {
            var point = new JoinPoint(this, export);

            _exportPoints.Add(export, point);
        }