コード例 #1
0
        /// <summary>
        /// Constructor used for the top-level search
        /// </summary>
        /// <param name="type"></param>
        /// <param name="owner"></param>
        public TargetTypeSelectorParams(Type type, TargetTypeSelector owner)
            : this(type)
        {
            RootTargets = owner?.RootTargets;
            // variance always starts off enabled.
            EnableVariance = true;

            bool enableContravariance = true;

            this._forceContravariance = GetInternalContravarianceOverride(Type);
            if (this._forceContravariance == null)
            {
                if (RootTargets != null)
                {
                    enableContravariance = RootTargets.GetOption(
                        Type, Options.EnableContravariance.Default);
                }
            }
            else
            {
                enableContravariance = this._forceContravariance.Value;
            }

            if (enableContravariance)
            {
                Contravariance = Contravariance.BasesAndInterfaces;
            }
            else
            {
                Contravariance = Contravariance.None;
            }
        }
コード例 #2
0
        /// <summary>
        /// Implementation of <see cref="ICovariantTypeIndex.SelectTypes(Type)"/>
        /// </summary>
        /// <param name="type">The type for which a search is to be run.</param>
        /// <returns>A <see cref="TargetTypeSelector"/></returns>
        public TargetTypeSelector SelectTypes(Type type)
        {
            // this function is complicated by the fact that searching and registering types are asymmetrically parallel.
            // in theory most applications will register first and then start searching.  However, the searching part is parallelised
            // equally, if registrations continue whilst searching is being performed, then we'd have a problem.  So this is written to
            // ensure that the cached type selectors stay up to date as extra registrations are made.
            var  result           = _cachedSearches.GetOrAdd(type, CreateSelector);
            long resultVersion    = Interlocked.Read(ref result.Version);
            long currentVersion   = Interlocked.Read(ref _version);
            long oldResultVersion = resultVersion;

            // it's fresh enough
            if (resultVersion == currentVersion)
            {
                return(result.Selector);
            }

            while (true)
            {
                resultVersion  = Interlocked.Read(ref result.Version);
                currentVersion = Interlocked.Read(ref _version);
                var newSelector = new TargetTypeSelector(type, _root);
                result.Selector = newSelector;
                if (Interlocked.CompareExchange(ref result.Version, currentVersion, resultVersion) == resultVersion)
                {
                    break;
                }
            }

            return(result.Selector);

            CachedTargetTypeSelector CreateSelector(Type t)
            {
                return(new CachedTargetTypeSelector()
                {
                    Version = Interlocked.Read(ref _version), Selector = new TargetTypeSelector(t, _root)
                });
            }
        }