示例#1
0
        /// <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);
        }
示例#2
0
        /// <summary>
        /// Gets the accessor object that can be used to invoke the method, field, or property on the type of object with the
        /// given return value and arguments.
        /// </summary>
        /// <param name="returnType">The return type of the method, field, or property.</param>
        /// <param name="arguments">The arguments passed to the method, field, or property.</param>
        /// <returns>An object which can be used to invoke the member that matches the given name, return type,
        /// and arguments.
        /// </returns>
        public MemberInfoAccessor GetTargetAccessor(Type returnType, object[] arguments)
        {
            // get an array of members
            MemberInfo[] members = Type.GetMember(TargetName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            // look for the member that will fit the caller
            foreach (MemberInfo member in members)
            {
                if (member.MemberType == MemberTypes.Property)
                {
                    PropertyInfo propertyInfo      = member as PropertyInfo;
                    MethodInfo   propertyGetMethod = propertyInfo.GetGetMethod(true);
                    if (MemberInfoAccessor.VerifyMatch(propertyGetMethod, returnType, arguments))
                    {
                        return(MemberInfoAccessor.BindMember(propertyGetMethod));
                    }

                    MethodInfo propertySetMethod = propertyInfo.GetSetMethod(true);
                    if (MemberInfoAccessor.VerifyMatch(propertySetMethod, returnType, arguments))
                    {
                        return(MemberInfoAccessor.BindMember(propertySetMethod));
                    }
                }
                else if (member.MemberType == MemberTypes.Field)
                {
                    FieldInfo fieldInfo = member as FieldInfo;
                    if ((returnType == fieldInfo.FieldType && arguments.Length == 0))
                    {
                        return(MemberInfoAccessor.BindMember(fieldInfo));
                    }

                    if (returnType == typeof(void) && arguments.Length == 1 && arguments[0].GetType().IsAssignableFrom(fieldInfo.FieldType))
                    {
                        return(MemberInfoAccessor.BindMember(fieldInfo));
                    }
                }
                else if (member.MemberType == MemberTypes.Method)
                {
                    MethodInfo methodInfo = member as MethodInfo;
                    if (MemberInfoAccessor.VerifyMatch(methodInfo, returnType, arguments))
                    {
                        return(MemberInfoAccessor.BindMember(methodInfo));
                    }
                }
            }

            throw new MissingProxyTargetException();
        }
示例#3
0
        /// <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));
        }
示例#4
0
        /// <summary>
        /// Gets the attribute that should be used for a given object instance.
        /// </summary>
        /// <param name="instance">The object instance that is going to be invoked by
        /// this method stub.</param>
        /// <returns>The attributes governing the invocation of methods on the instance object.</returns>
        /// <remarks>
        /// This method returns the best match attribute for the instance object.  For example, if the object
        /// instance is of type TextBox, and the list of bindings contains entries for the TextBoxBase and the
        /// Control classes, then the attributes for the TextBoxBase would be used for this object, since
        /// TextBoxBase is closer to TextBox in the inheritance hierarchy than Control.
        /// </remarks>
        public ProxyTypeBindingAttribute GetTypeBinding(object instance)
        {
            // get the instance of the type to get the attributes for
            Type instanceType = instance.GetType();

            // if the type is already here, return it
            if (typeBindings.ContainsKey(instanceType))
            {
                return(typeBindings[instanceType]);
            }

            // look for the correct type, which is the type in the list that is closest to the instance type in the inheritance hierarcy
            Type correctType = null;

            foreach (Type type in typeBindings.Keys)
            {
                if (type.IsAssignableFrom(instanceType) && (correctType == null || correctType.IsAssignableFrom(type)))
                {
                    correctType = type;
                }
            }

            // if no types are in the inheritance hierarchy, use the instance type
            if (correctType == null)
            {
                correctType = instanceType;
            }

            // if the type isn't in the list, assume that the method/property/field has the same name
            if (!typeBindings.ContainsKey(correctType))
            {
                if (MemberInfoAccessor.IsGetMethod(Method) || MemberInfoAccessor.IsSetMethod(Method))
                {
                    typeBindings.Add(correctType, new ProxyTypeBindingAttribute(correctType, MemberInfoAccessor.GetProperty(Method).Name));
                }
                else
                {
                    typeBindings.Add(correctType, new ProxyTypeBindingAttribute(correctType, Method.Name));
                }
            }

            return(typeBindings[correctType]);
        }
示例#5
0
        /// <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);
            }
        }
示例#6
0
        /// <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);
            }
        }
示例#7
0
        /// <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);
        }