bool Equals(ArrayKey <T> other) { if (other == null) { return(false); } if (other._hashCode != _hashCode) { return(false); } if (other._keys.Length != _keys.Length) { return(false); } for (int i = 0; i < _keys.Length; i++) { if (!object.Equals(_keys[i], other._keys[i])) { return(false); } } return(true); }
// Automagically guess the property relationships between various POCOs and create a delegate that will set them up public static object GetAutoMapper(Type[] types) { // Build a key var key = new ArrayKey <Type>(types); return(AutoMappers.Get(key, () => { // Create a method var m = new DynamicMethod("petapoco_automapper", types[0], types, true); var il = m.GetILGenerator(); for (int i = 1; i < types.Length; i++) { bool handled = false; for (int j = i - 1; j >= 0; j--) { // Find the property var candidates = from p in types[j].GetProperties() where p.PropertyType == types[i] select p; if (candidates.Count() == 0) { continue; } if (candidates.Count() > 1) { throw new InvalidOperationException(string.Format("Can't auto join {0} as {1} has more than one property of type {0}", types[i], types[j])); } // Generate code il.Emit(OpCodes.Ldarg_S, j); il.Emit(OpCodes.Ldarg_S, i); il.Emit(OpCodes.Callvirt, candidates.First().GetSetMethod(true)); handled = true; } if (!handled) { throw new InvalidOperationException(string.Format("Can't auto join {0}", types[i])); } } il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ret); // Cache it return m.CreateDelegate(Expression.GetFuncType(types.Concat(types.Take(1)).ToArray())); } )); }