/// <summary> /// Merge two different object instances into a single object which is a super-set of the properties of both objects. /// If property name collision occurs and no policy has been created to specify which to use using the .Use() method the property value from 'values1' will be used. /// </summary> /// <param name="values1">An object to be merged.</param> /// <param name="values2">An object to be merged.</param> /// <returns>New object containing properties from both objects</returns> public static object Merge(object values1, object values2) { lock (Mutex) { // Create a name from the names of both Types var name = $"{values1.GetType()}_{values2.GetType()}"; if (_typeMergerPolicy != null) { name += "_" + String.Join(",", _typeMergerPolicy.IgnoredProperties.Select(x => $"{x.Item1}_{x.Item2}")); } // Now that we're inside the lock - check one more time var result = CreateInstance(name, values1, values2); if (result != null) { _typeMergerPolicy = null; return(result); } // Merge list of PropertyDescriptors for both objects var pdc = GetProperties(values1, values2); // Make sure static properties are properly initialized InitializeAssembly(); // Create the type definition var newType = CreateType(name, pdc); // Add it to the cache ObjectTypeCache.Add(name, newType); // Return an instance of the new Type result = CreateInstance(name, values1, values2); _typeMergerPolicy = null; return(result); } }
/// <summary> /// Used internally by the TypeMergerPolicy class method chaining for specifying a policy to use during merging. /// </summary> internal static object Merge(object values1, object values2, TypeMergerPolicy policy) { _typeMergerPolicy = policy; return(Merge(values1, values2)); }