/// <summary>
        /// Create an implementation of the given interface, using the given requester
        /// </summary>
        /// <typeparam name="T">Type of interface to implement</typeparam>
        /// <param name="requester">Requester to be used by the generated implementation</param>
        /// <returns>An implementation of the given interface</returns>
        public T CreateImplementation <T>(IRequester requester)
        {
            if (requester == null)
            {
                throw new ArgumentNullException(nameof(requester));
            }

            // We have to be careful here. The common case is going to be fetching an existing creator. However in the case
            // that one doesn't yet exist, we can't try and create two of the same type at the same time.
            // We have a lock around creating all types, as that's simpler and probably won't be noticable in practice.

            if (TypeCreatorRegistry <T> .Creator == null)
            {
                lock (this.implementationBuilderLockObject)
                {
                    // Two threads can fail the null test and acquire this lock in order. The first one will create the type.
                    // Therefore the second one has to check for this...
                    if (TypeCreatorRegistry <T> .Creator == null)
                    {
                        var implementationType = this.BuildImplementationImpl(typeof(T));
                        var creator            = this.BuildCreator <T>(implementationType);
                        TypeCreatorRegistry <T> .Creator = creator;
                    }
                }
            }

            T implementation = TypeCreatorRegistry <T> .Creator(requester);

            return(implementation);
        }
Esempio n. 2
0
        /// <summary>
        /// Create an implementation of the given interface, using the given requester
        /// </summary>
        /// <typeparam name="T">Type of interface to implement</typeparam>
        /// <param name="requester">Requester to be used by the generated implementation</param>
        /// <returns>An implementation of the given interface</returns>
        public T CreateImplementation <T>(IRequester requester)
        {
            if (requester == null)
            {
                throw new ArgumentNullException(nameof(requester));
            }

            // We have to be careful here. The common case is going to be fetching an existing creator. However in the case
            // that one doesn't yet exist, we can't try and create two of the same type at the same time.
            // We have a lock around creating all types, as that's simpler and probably won't be noticable in practice.

            if (TypeCreatorRegistry <T> .Creator == null)
            {
                lock (this.implementationFactoryLockObject)
                {
                    // Two threads can fail the null test and acquire this lock in order. The first one will create the type.
                    // Therefore the second one has to check for this...
                    if (TypeCreatorRegistry <T> .Creator == null)
                    {
                        try
                        {
                            var implementationType = this.GetImplementation(typeof(T));
                            var creator            = this.BuildCreator <T>(implementationType);
                            TypeCreatorRegistry <T> .Creator = creator;
                        }
                        catch (Exception e)
                        {
                            // If they request the same type again, make sure they get the same exception. If we try and build the type
                            // again, they'll get a different exception about a duplicate type.
                            // Yes we nuke the stack trace, but that's not the end of the world since they don't care about our internals
                            TypeCreatorRegistry <T> .Creator = x => throw e;
                            throw;
                        }
                    }
                }
            }

            T implementation = TypeCreatorRegistry <T> .Creator(requester);

            return(implementation);
        }