/// <summary> /// Invokes proxy methods which return a value. /// </summary> /// <typeparam name="T">The return type of the method being invoked.</typeparam> /// <param name="args">The arguments to pass to the method.</param> /// <returns>The return value of the default proxy method.</returns> /// <remarks>This method will invoke methods on all of the proxy objects, but will return /// the result of the invocation on the default object. /// </remarks> protected T ProxyInvoke <T>(params object[] args) { if (objects.Count == 0) { return(default(T)); } StackTrace trace = new StackTrace(); StackFrame frame = trace.GetFrame(1); MethodInfo method = frame.GetMethod() as MethodInfo; ProxyAttributeCollection attributes = GetAttributes(method); bool first = true; T result = default(T); foreach (object invoke in objects) { ProxyTypeBindingAttribute binding = attributes.GetTypeBinding(invoke); MemberInfoAccessor accessor = binding.GetTargetAccessor(typeof(T), args); if (first) { result = (T)accessor.Get(invoke, args); first = false; } else { accessor.Get(invoke, args); } } return(result); }
/// <summary> /// Gets the <see cref="ProxyAttributeCollection"/> for a given <see cref="MethodInfo"/>. /// </summary> /// <param name="method">The method to get the proxy attributes for.</param> /// <returns>The collection of attributes for the given method as /// revealed by reflection of the method's attributes. /// </returns> private ProxyAttributeCollection GetAttributes(MethodInfo method) { if (!attributes.ContainsKey(method)) { ProxyAttributeCollection collection = ReflectMethod(method); attributes.Add(method, collection); } return(attributes[method]); }
/// <summary> /// Performs the get operation on the first object in the list of proxy objects (the default object). /// </summary> /// <typeparam name="T">The type to cast the return value as.</typeparam> /// <param name="args">The indices to pass to the get method.</param> /// <returns>The result of executing a get operation on the default proxy object, or the default value of T /// if there are no proxy objects. /// </returns> public T ProxyGet <T>(params object[] args) { if (objects.Count == 0) { return(default(T)); } StackTrace trace = new StackTrace(); StackFrame frame = trace.GetFrame(1); MethodInfo method = frame.GetMethod() as MethodInfo; ProxyAttributeCollection attributes = GetAttributes(method); ProxyTypeBindingAttribute binding = attributes.GetTypeBinding(objects[0]); MemberInfoAccessor accessor = binding.GetTargetAccessor(typeof(T), args); return((T)accessor.Get(objects[0], args)); }
/// <summary> /// Invokes proxy methods which do not return a value. /// </summary> /// <param name="args">The arguments to pass to the method.</param> protected void ProxyInvoke(params object[] args) { if (objects.Count == 0) { return; } StackTrace trace = new StackTrace(); StackFrame frame = trace.GetFrame(1); MethodInfo method = frame.GetMethod() as MethodInfo; ProxyAttributeCollection attributes = GetAttributes(method); foreach (object invoke in objects) { ProxyTypeBindingAttribute binding = attributes.GetTypeBinding(invoke); MemberInfoAccessor accessor = binding.GetTargetAccessor(typeof(void), args); accessor.Get(invoke, args); } }
/// <summary> /// Performs the set operation on all proxy objects. /// </summary> /// <param name="value">The value to set on the proxy objects.</param> /// <param name="args">The indices of the set operation.</param> protected void ProxySet(object value, params object[] args) { if (objects.Count == 0) { return; } StackTrace trace = new StackTrace(); StackFrame frame = trace.GetFrame(1); MethodInfo method = frame.GetMethod() as MethodInfo; ProxyAttributeCollection attributes = GetAttributes(method); foreach (object invoke in objects) { ProxyTypeBindingAttribute binding = attributes.GetTypeBinding(invoke); object[] argsWithValue = new object[args.Length + 1]; argsWithValue[0] = value; Array.Copy(args, 0, argsWithValue, 1, args.Length); MemberInfoAccessor accessor = binding.GetTargetAccessor(typeof(void), argsWithValue); accessor.Set(invoke, value, args); } }
/// <summary> /// Performs reflection on a method in order to determine which methods on proxy objects /// the method stub is bound to. /// </summary> /// <param name="method">The method to reflect over.</param> /// <returns>The collection of attributes about the method.</returns> private ProxyAttributeCollection ReflectMethod(MethodInfo method) { ProxyAttributeCollection collection = new ProxyAttributeCollection(method); // get the information that is applied directly to the method object[] typeBindings = method.GetCustomAttributes(typeof(ProxyTypeBindingAttribute), true); foreach (ProxyTypeBindingAttribute attribute in typeBindings) { collection.AddTypeBinding(attribute); } // if the method is a get or set method on a property, also get the attributes applied to the property if (MemberInfoAccessor.IsGetMethod(method) || MemberInfoAccessor.IsSetMethod(method)) { PropertyInfo propertyInfo = MemberInfoAccessor.GetProperty(method); object[] moreBindings = propertyInfo.GetCustomAttributes(typeof(ProxyTypeBindingAttribute), true); foreach (ProxyTypeBindingAttribute attribute in moreBindings) { collection.AddTypeBinding(attribute); } } return(collection); }