//****************************************************************************************************** // FastObjectFactory.cs - Gbtc // // Copyright © 2012, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 01/25/2010 - James R. Carroll // Generated original version of source code. // 12/14/2012 - Starlynn Danyelle Gilliam // Modified Header. // 12/20/2013 - Pinal C. Patel // Updated the dictionary used for caching the activators returned by GetCreateObjectFunction() // to not use Type for the key but instead use a combined hash of Type whose activator is to be // created along with the Type being returned. This enables scenarios where multiple activators // of the same type needs to be created but the return type needs to different. // //****************************************************************************************************** using System; using System.Collections.Concurrent; using System.Reflection; using System.Reflection.Emit; namespace GSF { /// /// Quickly creates new objects based on specified type. /// /// Type of object to create quickly. /// /// You can use the alternate implementation if you only have the of /// an object available (such as when you are using reflection). /// public static class FastObjectFactory where T : class, new() { // Static object creation delegate specific to type T - one instance will be created per type by the compiler private static readonly Func s_createObjectFunction; static FastObjectFactory() { Type type = typeof(T); ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes); if ((object)constructor == null) throw new InvalidOperationException("No parameterless constructor exists for type " + type.FullName); // This is markedly faster than using Activator.CreateInstance DynamicMethod method = new DynamicMethod("ctor$" + type.Name, type, null, type); ILGenerator generator = method.GetILGenerator(); generator.Emit(OpCodes.Newobj, constructor); generator.Emit(OpCodes.Ret); s_createObjectFunction = (Func)method.CreateDelegate(typeof(Func)); } /// /// Gets delegate that quickly creates new instance of the specified type. /// public static Func CreateObjectFunction { get { return s_createObjectFunction; } } } /// /// Quickly creates new objects based on specified type. /// /// /// should be used when you only have the of an object available (such as when you are /// using reflection), otherwise you should use the generic . /// public static class FastObjectFactory { // We cache object creation functions by type so they are only created once private static readonly ConcurrentDictionary s_createObjectFunctions = new ConcurrentDictionary(); /// /// Gets delegate that creates new instance of the . /// /// Type of object to create quickly. /// Delegate to use to quickly create new objects. /// does not support parameterless public constructor. public static Func GetCreateObjectFunction(Type type) { return GetCreateObjectFunction(type); } /// /// Gets delegate of specified return type that creates new instance of the . /// /// Type of object to create quickly. /// Type of returned object function used to create objects quickly. /// Delegate to use to quickly create new objects. /// /// does not support parameterless public constructor -or- /// is not a subclass or interface implementation of function type definition. /// /// /// This function will validate that is related to . /// public static Func GetCreateObjectFunction(Type type) { // Since user can call this function with any type, we verify that it is related to the return type. If return type // is a class, see if type derives from it, else if return type is an interface, see if type implements it. Type typeT = typeof(T); if (type.IsAbstract || ((!typeT.IsClass || !type.IsSubclassOf(typeT)) && (!typeT.IsInterface || (object)type.GetInterface(typeT.Name) == null))) throw new InvalidOperationException("Specified type parameter is not a subclass or interface implementation of function type definition"); int key; #if MONO // Type.GUID always returns zero guid on Mono key = type.FullName.GetHashCode() ^ typeT.FullName.GetHashCode(); #else key = type.GUID.GetHashCode() ^ typeT.GUID.GetHashCode(); #endif return (Func)s_createObjectFunctions.GetOrAdd(key, k => { // Get parameterless constructor for this type ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes); if ((object)constructor == null) throw new InvalidOperationException("No parameterless constructor exists for type " + type.FullName); // This is markedly faster than using Activator.CreateInstance DynamicMethod method = new DynamicMethod("ctor_type$" + type.Name, type, null, type); ILGenerator generator = method.GetILGenerator(); generator.Emit(OpCodes.Newobj, constructor); generator.Emit(OpCodes.Ret); return (Func)method.CreateDelegate(typeof(Func)); }); } } }