Пример #1
0
        /// <summary>
        /// Creates and returns an instance of a class or interface T with given constructor arguments (<paramref name="data"/>).
        /// </summary>
        /// <typeparam name="T">type of the interface to instantiate</typeparam>
        /// <param name="instantiatorKey"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        /// <exception cref="InstantiatorException"></exception>
        public T Instantiate(InstantiatorKey instantiatorKey, params object[] data)
        {
            try
            {
                var instance = CreateInstance(instantiatorKey, data);
                if (instance != null)
                {
                    return(instance);
                }

                // OK. We did not find an instantiator. Let's try to create one. First of all let's lock an object
                var lockObject1 = new object();
                lock (lockObject1)
                {
                    if (InstantiatorLocks.TryAdd(instantiatorKey, lockObject1))
                    {
                        // if we ended up here, it means that we were first
                        Instantiators.AddRange(CreateInstantiatorsForPackage(instantiatorKey));
                    }
                    else
                    {
                        // some other process have already created (or creating) instantiator
                        // Theoretically, it is quite possible to have previous process fail, so we will need to be careful about assuming that if we got here,
                        // then we should have instantiators.
                        lock (InstantiatorLocks[instantiatorKey])
                        {
                            // try read from the instantiators first. Maybe it has already been successfully created
                            instance = CreateInstance(instantiatorKey, data);
                            if (instance != null)
                            {
                                return(instance);
                            }
                            Instantiators.AddRange(CreateInstantiatorsForPackage(instantiatorKey));
                        }
                    }
                    instance = CreateInstance(instantiatorKey, data);
                    if (instance != null)
                    {
                        return(instance);
                    }
                }
            }
            catch (Exception e)
            {
                throw new InstantiatorException("Error occurred during instantiation", e);
            }

            throw new InstantiatorException($"Unknown error. Instantiator failed to produce an instance of {instantiatorKey}", null);
        }
Пример #2
0
        /// <summary>
        /// Creates an instance of a generic type T.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="instantiatorKey"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private static T CreateInstance(InstantiatorKey instantiatorKey, object[] data)
        {
            if (!Instantiators.ContainsKey(instantiatorKey))
            {
                return(default(T));
            }

            var instantiatorByType = Instantiators[instantiatorKey];

            // here it make sense to concatenate params
            var paramsHash = data == null || !data.Any() ? "" : string.Join(", ", data.Select(d => d.GetType().FullName));

            if (instantiatorByType.ContainsKey(paramsHash))
            {
                return(instantiatorByType[paramsHash](data));
            }

            throw new InstantiatorException(
                      $"Constructor signature {paramsHash} not found for package {instantiatorKey}", null);
        }