WorkflowInstanceExtensionCollection.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.Activities / System / Activities / Hosting / WorkflowInstanceExtensionCollection.cs / 1305376 / WorkflowInstanceExtensionCollection.cs

                            //---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------

namespace System.Activities.Hosting 
{
    using System.Activities.Tracking; 
    using System.Collections.Generic; 
    using System.Linq;
    using System.Runtime; 

    class WorkflowInstanceExtensionCollection
    {
        List> instanceExtensions; 
        List additionalInstanceExtensions;
        List allSingletonExtensions; 
        bool hasTrackingParticipant; 
        bool hasPersistenceModule;
        bool shouldSetInstanceForInstanceExtensions; 

        // cache for cases where we have a single match
        Dictionary singleTypeCache;
 
        List workflowInstanceExtensions;
 
        // optimization for common extension in a loop/parallel (like Compensation or Send) 
        Type lastTypeCached;
        object lastObjectCached; 

        // temporary pointer to our parent manager between ctor and Initialize
        WorkflowInstanceExtensionManager extensionManager;
 
        internal WorkflowInstanceExtensionCollection(Activity workflowDefinition, WorkflowInstanceExtensionManager extensionManager)
        { 
            this.extensionManager = extensionManager; 

            int extensionProviderCount = 0; 
            if (extensionManager != null)
            {
                extensionProviderCount = extensionManager.ExtensionProviders.Count;
                this.hasTrackingParticipant = extensionManager.HasSingletonTrackingParticipant; 
                this.hasPersistenceModule = extensionManager.HasSingletonPersistenceModule;
 
                // create an uber-IEnumerable to simplify our iteration code 
                this.allSingletonExtensions = this.extensionManager.GetAllSingletonExtensions();
            } 
            else
            {
                this.allSingletonExtensions = WorkflowInstanceExtensionManager.EmptySingletonExtensions;
            } 

            // Resolve activity extensions 
            Dictionary activityExtensionProviders; 
            Dictionary filteredActivityExtensionProviders = null;
            HashSet requiredActivityExtensionTypes; 
            if (workflowDefinition.GetActivityExtensionInformation(out activityExtensionProviders, out requiredActivityExtensionTypes))
            {
                // a) filter out the extension Types that were already configured by the host. Note that only "primary" extensions are in play here, not
                // "additional" extensions 
                HashSet allExtensionTypes = new HashSet();
                if (extensionManager != null) 
                { 
                    extensionManager.AddAllExtensionTypes(allExtensionTypes);
                } 

                if (activityExtensionProviders != null)
                {
                    filteredActivityExtensionProviders = new Dictionary(activityExtensionProviders.Count); 
                    foreach (KeyValuePair keyedActivityExtensionProvider in activityExtensionProviders)
                    { 
                        Type newExtensionProviderType = keyedActivityExtensionProvider.Key; 
                        if (!TypeHelper.ContainsCompatibleType(allExtensionTypes, newExtensionProviderType))
                        { 
                            // first see if the new provider supersedes any existing ones
                            List typesToRemove = null;
                            bool skipNewExtensionProvider = false;
                            foreach (Type existingExtensionProviderType in filteredActivityExtensionProviders.Keys) 
                            {
                                // Use AreReferenceTypesCompatible for performance since we know that all of these must be reference types 
                                if (TypeHelper.AreReferenceTypesCompatible(existingExtensionProviderType, newExtensionProviderType)) 
                                {
                                    skipNewExtensionProvider = true; 
                                    break;
                                }

                                if (TypeHelper.AreReferenceTypesCompatible(newExtensionProviderType, existingExtensionProviderType)) 
                                {
                                    if (typesToRemove == null) 
                                    { 
                                        typesToRemove = new List();
                                    } 
                                    typesToRemove.Add(existingExtensionProviderType);
                                }
                            }
 
                            // prune unnecessary extension providers (either superseded by the new extension or by an existing extension that supersedes them both)
                            if (typesToRemove != null) 
                            { 
                                for (int i = 0; i < typesToRemove.Count; i++)
                                { 
                                    filteredActivityExtensionProviders.Remove(typesToRemove[i]);
                                }
                            }
 
                            // and add a new extension if necessary
                            if (!skipNewExtensionProvider) 
                            { 
                                filteredActivityExtensionProviders.Add(newExtensionProviderType, keyedActivityExtensionProvider.Value);
                            } 
                        }
                    }
                    if (filteredActivityExtensionProviders.Count > 0)
                    { 
                        allExtensionTypes.UnionWith(filteredActivityExtensionProviders.Keys);
                        extensionProviderCount += filteredActivityExtensionProviders.Count; 
                    } 
                }
 
                // b) Validate that all required extensions will be provided
                if (requiredActivityExtensionTypes != null && requiredActivityExtensionTypes.Count > 0)
                {
                    foreach (Type requiredType in requiredActivityExtensionTypes) 
                    {
                        if (!TypeHelper.ContainsCompatibleType(allExtensionTypes, requiredType)) 
                        { 
                            throw FxTrace.Exception.AsError(new ValidationException(SR.RequiredExtensionTypeNotFound(requiredType.ToString())));
                        } 
                    }
                }
            }
 
            // Finally, if our checks of passed, resolve our delegates
            if (extensionProviderCount > 0) 
            { 
                this.instanceExtensions = new List>(extensionProviderCount);
 
                if (extensionManager != null)
                {
                    List> extensionProviders = extensionManager.ExtensionProviders;
                    for (int i = 0; i < extensionProviders.Count; i++) 
                    {
                        KeyValuePair extensionProvider = extensionProviders[i]; 
                        AddInstanceExtension(extensionProvider.Value); 
                    }
                } 

                if (filteredActivityExtensionProviders != null)
                {
                    foreach (WorkflowInstanceExtensionProvider extensionProvider in filteredActivityExtensionProviders.Values) 
                    {
                        AddInstanceExtension(extensionProvider); 
                    } 
                }
            } 
        }

        void AddInstanceExtension(WorkflowInstanceExtensionProvider extensionProvider)
        { 
            Fx.Assert(this.instanceExtensions != null, "instanceExtensions should be setup by now");
            object newExtension = extensionProvider.ProvideValue(); 
            if (newExtension is SymbolResolver) 
            {
                throw FxTrace.Exception.AsError(new InvalidOperationException(SR.SymbolResolverMustBeSingleton)); 
            }

            // for IWorkflowInstance we key off the type of the value, not the declared type
            if (!this.shouldSetInstanceForInstanceExtensions && newExtension is IWorkflowInstanceExtension) 
            {
                this.shouldSetInstanceForInstanceExtensions = true; 
            } 
            if (!this.hasTrackingParticipant && extensionProvider.IsMatch(newExtension))
            { 
                this.hasTrackingParticipant = true;
            }
            if (!this.hasPersistenceModule && extensionProvider.IsMatch(newExtension))
            { 
                this.hasPersistenceModule = true;
            } 
 
            this.instanceExtensions.Add(new KeyValuePair(extensionProvider, newExtension));
 
            WorkflowInstanceExtensionManager.AddExtensionClosure(newExtension, ref this.additionalInstanceExtensions, ref this.hasTrackingParticipant, ref this.hasPersistenceModule);
        }

        internal bool HasPersistenceModule 
        {
            get 
            { 
                return this.hasPersistenceModule;
            } 
        }

        internal bool HasTrackingParticipant
        { 
            get
            { 
                return this.hasTrackingParticipant; 
            }
        } 

        public bool HasWorkflowInstanceExtensions
        {
            get 
            {
                return this.workflowInstanceExtensions != null && this.workflowInstanceExtensions.Count > 0; 
            } 
        }
 
        public List WorkflowInstanceExtensions
        {
            get
            { 
                return this.workflowInstanceExtensions;
            } 
        } 

        internal void Initialize() 
        {
            if (this.extensionManager != null)
            {
                // if we have any singleton IWorkflowInstanceExtensions, initialize them first 
                // All validation logic for singletons is done through WorkflowInstanceExtensionManager
                if (this.extensionManager.HasSingletonIWorkflowInstanceExtensions) 
                { 
                    SetInstance(this.extensionManager.SingletonExtensions);
 
                    if (this.extensionManager.HasAdditionalSingletonIWorkflowInstanceExtensions)
                    {
                        SetInstance(this.extensionManager.AdditionalSingletonExtensions);
                    } 
                }
            } 
 
            if (this.shouldSetInstanceForInstanceExtensions)
            { 
                for (int i = 0; i < this.instanceExtensions.Count; i++)
                {
                    KeyValuePair keyedExtension = this.instanceExtensions[i];
                    // for IWorkflowInstance we key off the type of the value, not the declared type 
                    IWorkflowInstanceExtension workflowInstanceExtension = keyedExtension.Value as IWorkflowInstanceExtension;
 
                    if (workflowInstanceExtension != null) 
                    {
                        if (this.workflowInstanceExtensions == null) 
                        {
                            this.workflowInstanceExtensions = new List();
                        }
 
                        this.workflowInstanceExtensions.Add(workflowInstanceExtension);
                    } 
                } 

                if (this.additionalInstanceExtensions != null) 
                {
                    SetInstance(this.additionalInstanceExtensions);
                }
            } 
        }
 
        void SetInstance(List extensionsList) 
        {
            for (int i = 0; i < extensionsList.Count; i++) 
            {
                object extension = extensionsList[i];
                if (extension is IWorkflowInstanceExtension)
                { 
                    if (this.workflowInstanceExtensions == null)
                    { 
                        this.workflowInstanceExtensions = new List(); 
                    }
 
                    this.workflowInstanceExtensions.Add((IWorkflowInstanceExtension)extension);
                }
            }
        } 

        public T Find() 
            where T : class 
        {
            T result = null; 

            object cachedExtension;
            if (TryGetCachedExtension(typeof(T), out cachedExtension))
            { 
                return (T)cachedExtension;
            } 
 
            try
            { 
                // when we have support for context.GetExtensions(), then change from early break to ThrowOnMultipleMatches ("There are more than one matched extensions found which is not allowed with GetExtension method call. Please use GetExtensions method instead.")
                for (int i = 0; i < this.allSingletonExtensions.Count; i++)
                {
                    object extension = this.allSingletonExtensions[i]; 
                    result = extension as T;
                    if (result != null) 
                    { 
                        return result;
                    } 
                }

                if (this.instanceExtensions != null)
                { 
                    for (int i = 0; i < this.instanceExtensions.Count; i++)
                    { 
                        KeyValuePair keyedExtension = this.instanceExtensions[i]; 
                        if (keyedExtension.Key.IsMatch(keyedExtension.Value))
                        { 
                            result = (T)keyedExtension.Value;
                            return result;
                        }
                    } 

                    if (this.additionalInstanceExtensions != null) 
                    { 
                        for (int i = 0; i < this.additionalInstanceExtensions.Count; i++)
                        { 
                            object additionalExtension = this.additionalInstanceExtensions[i];
                            result = additionalExtension as T;
                            if (result != null)
                            { 
                                return result;
                            } 
                        } 
                    }
                } 

                return result;
            }
            finally 
            {
                CacheExtension(result); 
            } 
        }
 
        public IEnumerable FindAll()
            where T : class
        {
            return FindAll(false); 
        }
 
        IEnumerable FindAll(bool useObjectTypeForComparison) 
            where T : class
        { 
            // sometimes we match the single case even when you ask for multiple
            object cachedExtension;
            if (TryGetCachedExtension(typeof(T), out cachedExtension))
            { 
                yield return (T)cachedExtension;
            } 
            else 
            {
                T lastExtension = null; 
                bool hasMultiple = false;

                foreach (T extension in this.allSingletonExtensions.OfType())
                { 
                    if (lastExtension == null)
                    { 
                        lastExtension = extension; 
                    }
                    else 
                    {
                        hasMultiple = true;
                    }
 
                    yield return extension;
                } 
 
                foreach (T extension in GetInstanceExtensions(useObjectTypeForComparison))
                { 
                    if (lastExtension == null)
                    {
                        lastExtension = extension;
                    } 
                    else
                    { 
                        hasMultiple = true; 
                    }
 
                    yield return extension;
                }

                if (!hasMultiple) 
                {
                    CacheExtension(lastExtension); 
                } 
            }
        } 

        IEnumerable GetInstanceExtensions(bool useObjectTypeForComparison) where T : class
        {
            if (this.instanceExtensions != null) 
            {
                for (int i = 0; i < this.instanceExtensions.Count; i++) 
                { 
                    KeyValuePair keyedExtension = this.instanceExtensions[i];
                    if ((useObjectTypeForComparison && keyedExtension.Value is T) 
                        || keyedExtension.Key.IsMatch(keyedExtension.Value))
                    {
                        yield return (T)keyedExtension.Value;
                    } 
                }
 
                if (this.additionalInstanceExtensions != null) 
                {
                    foreach (object additionalExtension in this.additionalInstanceExtensions) 
                    {
                        if (additionalExtension is T)
                        {
                            yield return (T)additionalExtension; 
                        }
                    } 
                } 
            }
        } 

        public void Dispose()
        {
            // we should only call dispose on instance extensions, since those are 
            // the only ones we created
            foreach (IDisposable disposableExtension in GetInstanceExtensions(true)) 
            { 
                disposableExtension.Dispose();
            } 
        }

        public void Cancel()
        { 
            foreach (ICancelable cancelableExtension in GetInstanceExtensions(true))
            { 
                cancelableExtension.Cancel(); 
            }
        } 

        void CacheExtension(T extension)
            where T : class
        { 
            if (extension != null)
            { 
                CacheExtension(typeof(T), extension); 
            }
        } 

        void CacheExtension(Type extensionType, object extension)
        {
            if (extension != null) 
            {
                if (this.singleTypeCache == null) 
                { 
                    this.singleTypeCache = new Dictionary();
                } 

                this.lastTypeCached = extensionType;
                this.lastObjectCached = extension;
                this.singleTypeCache[extensionType] = extension; 
            }
        } 
 
        bool TryGetCachedExtension(Type type, out object extension)
        { 
            if (this.singleTypeCache == null)
            {
                extension = null;
                return false; 
            }
 
            if (object.ReferenceEquals(type, this.lastTypeCached)) 
            {
                extension = this.lastObjectCached; 
                return true;
            }

            return this.singleTypeCache.TryGetValue(type, out extension); 
        }
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK