/// <summary> /// Create an instance of the requested <see cref="Type"/> using the constructor that best matches the specified parameters. /// </summary> /// <typeparam name="T">The interface <see cref="Type"/> of the instance to create.</typeparam> /// <param name="args">An array of arguments that match in number, order, and type the parameters of the constructor to invoke. If <paramref name="args"/> /// is an empty array or <c>null</c>, the constructor that takes no parameters (the default constructor) is invoked.</param> /// <returns>An instance of the requested <see cref="Type"/>.</returns> public static T Create <T>(params object[] args) { Type typeKey = typeof(T); Type typeVal = null; if (_localProviderValues.Value != null && _localProviderValues.Value.ContainsKey(typeKey.AssemblyQualifiedName)) { return((T)_localProviderValues.Value[typeKey.AssemblyQualifiedName]); } if (_providerValues.ContainsKey(typeKey.AssemblyQualifiedName)) { return((T)_providerValues[typeKey.AssemblyQualifiedName]); } if (_typeCache.ContainsKey(typeKey)) { return((T)Activator.CreateInstance(_typeCache[typeKey], args)); } if (!typeKey.GetTypeInfo().IsInterface) { throw new InvalidOperationException(string.Format("Factory can not create an instance of Type '{0}' as this is not an Interface.", typeKey.AssemblyQualifiedName)); } if (_typeProviders.ContainsKey(typeKey.AssemblyQualifiedName)) { typeVal = Type.GetType(_typeProviders[typeKey.AssemblyQualifiedName], false); } else { // Assume concrete is the same name with the leading "I" removed or itself if not following that naming convention; e.g. IFoo is Foo. string concreteName = SubstitutionRegex.Replace(typeKey.Name, string.Empty); // Look in same Assembly as Interface for implementation (primary). if (concreteName != typeKey.Name) { typeVal = Type.GetType(MakeTypeName(typeKey, concreteName)); } // Look at namespace substitutions as it may reside in another assembly (secondary). if (typeVal == null) { foreach (var substitution in _substitutions.Where(x => x.Key == Substitution.CreateKey(typeKey))) { typeVal = Type.GetType(MakeTypeName(substitution.Concrete, SubstitutionRegex.Replace(typeKey.Name, string.Empty))); if (typeVal != null) { break; } } } } if (typeVal == null) { throw new InvalidOperationException(string.Format("Factory can not create an instance of Type '{0}'; please check the naming convention and substitution rules.", typeKey.AssemblyQualifiedName)); } lock (_lock) { if (_typeCache.ContainsKey(typeKey)) { return((T)Activator.CreateInstance(_typeCache[typeKey], args)); } _typeCache.Add(typeKey, typeVal); return((T)Activator.CreateInstance(typeVal, args)); } }