public bool Equals(MethodCallDelegateKey other) { if (ReferenceEquals(null, other)) { return(false); } if (other.hashCode != hashCode) { return(false); } var otherItems = other.items; if (otherItems.Length != items.Length) { return(false); } for (int i = 0; i < items.Length; i++) { if (!Equals(otherItems[i], items[i])) { return(false); } } return(true); }
/// <summary> /// Creates property \ member setter delegate. /// </summary> /// <typeparam name="TObject">Declaring type.</typeparam> /// <typeparam name="TValue">Member type.</typeparam> /// <param name="memberName">Member name.</param> /// <returns><see cref="Action{T,R}"/> delegate /// that sets member value.</returns> public static Action <TObject, TValue> CreateSetMemberDelegate <TObject, TValue>(string memberName) { Type type = typeof(TObject); Type tValue = typeof(TValue); var methodKey = new MethodCallDelegateKey(memberName, type, tValue); Action <TObject, TValue> result = (Action <TObject, TValue>)GetCachedDelegate(methodKey); if (result == null) { lock (cachedDelegates.SyncRoot) { result = (Action <TObject, TValue>)GetCachedDelegate(methodKey); if (result != null) { return(result); } PropertyInfo pi = type.GetProperty(memberName); FieldInfo fi = type.GetField(memberName); if (pi != null) { // Member is a Property... MethodInfo mi = pi.GetSetMethod(true); if (mi != null) { // Calling a property's get accessor is faster/cleaner using // Delegate.CreateDelegate rather than Reflection.Emit // TODO: Check that type conversion is adequate. result = (Action <TObject, TValue>)Delegate.CreateDelegate(typeof(Action <TObject, TValue>), mi); } else { throw new InvalidOperationException(string.Format(Strings.ExPropertyDoesNotHaveSetter, memberName, type.GetShortName())); } } else if (fi != null) { // Member is a Field... DynamicMethod dm = new DynamicMethod("Set" + memberName, typeof(TValue), new Type[] { type }, type); ILGenerator il = dm.GetILGenerator(); // Load the instance of the object (argument 0) onto the stack il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); // Load the value of the object's field (fi) onto the stack il.Emit(OpCodes.Stfld, fi); // return the value on the top of the stack il.Emit(OpCodes.Ldc_I4_1); il.Emit(OpCodes.Ret); result = (Action <TObject, TValue>)dm.CreateDelegate(typeof(Func <TObject, TValue>)); } else { throw new InvalidOperationException(string.Format(Strings.ExMemberIsNotPublicPropertyOrField, memberName, type.GetShortName())); } AddCachedDelegate(methodKey, result); } } return(result); }
/// <summary> /// Creates primitive type cast delegate - e.g. <see cref="Enum"/> to <see cref="sbyte"/>. /// </summary> /// <typeparam name="TSource">The type to cast.</typeparam> /// <typeparam name="TTarget">Target type.</typeparam> /// <returns>A delegate allowing to cast <typeparamref name="TSource"/> to <typeparamref name="TTarget"/>.</returns> /// <exception cref="InvalidCastException"><c>InvalidCastException</c>.</exception> public static Converter <TSource, TTarget> CreatePrimitiveCastDelegate <TSource, TTarget>() where TSource : struct where TTarget : struct { Type sourceType = typeof(TSource); Type targetType = typeof(TTarget); string methodName = string.Format("{0}_{1}_{2}", primitiveCastMethodName, sourceType, targetType); var methodKey = new MethodCallDelegateKey(methodName); var result = GetCachedDelegate(methodKey) as Converter <TSource, TTarget>; if (result == null) { lock (cachedDelegates.SyncRoot) { result = GetCachedDelegate(methodKey) as Converter <TSource, TTarget>; if (result != null) { return(result); } Type actualSourceType = sourceType; if (sourceType.IsEnum) { actualSourceType = Enum.GetUnderlyingType(sourceType); } if (!opCodeConv.ContainsKey(actualSourceType)) { throw new InvalidCastException(string.Format(Strings.ExInvalidCast, sourceType.GetShortName(), targetType.GetShortName())); } Type actualTargetType = targetType; if (targetType.IsEnum) { actualTargetType = Enum.GetUnderlyingType(targetType); } if (!opCodeConv.ContainsKey(actualTargetType)) { throw new InvalidCastException(string.Format(Strings.ExInvalidCast, sourceType.GetShortName(), targetType.GetShortName())); } DynamicMethod dm = new DynamicMethod(methodName, typeof(TTarget), new Type[] { sourceType }); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); if (targetType.IsEnum) { if (typeOnStack[actualSourceType] != typeOnStack[actualSourceType]) { il.Emit(opCodeConv[actualTargetType]); } } il.Emit(OpCodes.Ret); result = dm.CreateDelegate(typeof(Converter <TSource, TTarget>)) as Converter <TSource, TTarget>; AddCachedDelegate(methodKey, result); } } return(result); }
private static TDelegateType InnerCreateGetMemberDelegate <TObject, TValue, TDelegateType>(string memberName) where TDelegateType : class { Type type = typeof(TObject); Type tValue = typeof(TValue); var methodKey = new MethodCallDelegateKey(typeof(TDelegateType), memberName, type, tValue); TDelegateType result = GetCachedDelegate(methodKey) as TDelegateType; if (result == null) { lock (cachedDelegates.SyncRoot) { result = GetCachedDelegate(methodKey) as TDelegateType; if (result != null) { return(result); } PropertyInfo pi = type.GetProperty(memberName); FieldInfo fi = type.GetField(memberName); MethodInfo smi; if (pi != null) { // Member is a Property... MethodInfo mi = pi.GetGetMethod(true); if (mi != null) { // Calling a property's get accessor is faster/cleaner using // Delegate.CreateDelegate rather than Reflection.Emit result = Delegate.CreateDelegate(typeof(TDelegateType), mi) as TDelegateType; } else { throw new InvalidOperationException(string.Format(Strings.ExPropertyDoesNotHaveGetter, memberName, type.GetShortName())); } } else if (fi != null) { // Member is a Field... DynamicMethod dm = new DynamicMethod("Get" + memberName, typeof(TValue), new Type[] { type }, type); ILGenerator il = dm.GetILGenerator(); // Load the instance of the object (argument 0) onto the stack il.Emit(OpCodes.Ldarg_0); // Load the value of the object's field (fi) onto the stack il.Emit(OpCodes.Ldfld, fi); // return the value on the top of the stack il.Emit(OpCodes.Ret); result = dm.CreateDelegate(typeof(TDelegateType)) as TDelegateType; } else if (null != (smi = type.GetMethod(AspectedPrivateFieldGetterPrefix + memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.ExactBinding))) { result = Delegate.CreateDelegate(typeof(Func <TObject, TValue>), smi) as TDelegateType; } else { throw new InvalidOperationException(string.Format(Strings.ExMemberIsNotPublicPropertyOrField, memberName, type.GetShortName())); } AddCachedDelegate(methodKey, result as Delegate); } } return(result); }