/// <summary> /// Creates a proxy for this object /// </summary> /// <typeparam name="I">Interface to proxy</typeparam> /// <typeparam name="A">Will only proxy method that have this attribute</typeparam> /// <param name="objectToProxy"></param> /// <param name="interceptorDelegate">delegate to call on method invocation</param> /// <returns></returns> public static I Proxy <I, A>(this I objectToProxy, EmitProxyInterceptor <I> interceptorDelegate) where A : Attribute { return(Proxy <I>(objectToProxy, (info) => { //Check if hte attribute is on the interface //also check if our method info is actually a property value, if so we will check if the //attribute is on the property bool isAttributeOnInterface = typeof(I).GetMethod(info.Name, info.GetParameters().Select(p => p.ParameterType).ToArray()) != null; if (isAttributeOnInterface == false && info.IsSpecialName && (info.Name.StartsWith("get_") || info.Name.StartsWith("set_"))) { isAttributeOnInterface = typeof(I).GetProperty(info.Name.Remove(0, 4)) != null; } //Check if hte attribute is on our actual object //also check if our method info is actually a property value, if so we will check if the //attribute is on the property bool isAttributeOnMethod = info.GetCustomAttributes(typeof(A), true).Count() > 0; if (isAttributeOnMethod == false && info.IsSpecialName && (info.Name.StartsWith("get_") || info.Name.StartsWith("set_"))) { isAttributeOnMethod = objectToProxy.GetType().GetProperty(info.Name.Remove(0, 4)) != null; } //we have the attribute if it is either on the interface or method return isAttributeOnInterface || isAttributeOnMethod; }, interceptorDelegate)); }
/// <summary> /// Creates a proxy for this object /// </summary> /// <typeparam name="I">Interface to proxy</typeparam> /// <param name="objectToProxy"></param> /// <param name="interceptorDelegate">delegate to call on method invocation</param> /// <returns></returns> public static I Proxy <I>(this I objectToProxy, EmitProxyInterceptor <I> interceptorDelegate) { return(Proxy <I>(objectToProxy, (info) => true, interceptorDelegate)); }
/// <summary> /// Creates a proxy for this object /// </summary> /// <typeparam name="I">Interface to proxy</typeparam> /// <param name="objectToProxy"></param> /// <param name="methodSelector">predicate to select which methods call the <paramref name="interceptorDelegate"/> </param> /// <param name="interceptorDelegate">delegate to call on method invocation</param> /// <returns></returns> public static I Proxy <I>(this I objectToProxy, Predicate <MethodInfo> methodSelector, EmitProxyInterceptor <I> interceptorDelegate) { if (!typeof(I).IsInterface) { throw new Exception("Generic parameter must be an interface"); } //ensure we have something in our interface level cache if (!_dynamicTypeCache.ContainsKey(typeof(I))) { _dynamicTypeCache[typeof(I)] = new Dictionary <Predicate <MethodInfo>, Type>(); } //Check if the type is cached first, if not we go and emit a proxy class for the given interface //and pass null for the attribute we are proxying if (!_dynamicTypeCache[typeof(I)].ContainsKey(methodSelector)) { _dynamicTypeCache[typeof(I)][methodSelector] = CreateProxy <I>(objectToProxy, methodSelector, interceptorDelegate); } return((I)Activator.CreateInstance(_dynamicTypeCache[typeof(I)][methodSelector], objectToProxy, interceptorDelegate)); }
/// <summary> /// Creates a proxy /// </summary> /// <typeparam name="I">Interface of the proxy</typeparam> /// <param name="objectToProxy">object that is being proxied</param> /// <param name="interceptorDelegate">delegate to call on invocation</param> /// <param name="methodSelector">predicate to select which methods call the <paramref name="interceptorDelegate"/> </param> /// <returns>The proxy</returns> private static Type CreateProxy <I>(I objectToProxy, Predicate <MethodInfo> methodSelector, EmitProxyInterceptor <I> interceptorDelegate) { //create the dynamic assembly ModuleBuilder moduleBuilder = CreateAssembly(ASSEMBLY_NAME, MODULE_NAME); //create our new type that implements the proxy interface TypeBuilder typeBuilder = moduleBuilder.CreateType <I, object>(typeof(I).Name + TYPE_SUFFIX); //copy the class custom attributes foreach (CustomAttributeBuilder attrBuilder in CreateCustomAttributeBuilder(objectToProxy.GetType())) { typeBuilder.SetCustomAttribute(attrBuilder); } //create two fields, one to store the proxied object, and one to store the Interceptor delegate //this will also create a constructor to set both these values FieldInfo[] fieldInfo = typeBuilder.CreateFieldsAndConstrucutor( typeof(I), "ProxiedObject", typeof(EmitProxyInterceptor <I>), "Interceptor"); //Create an implementation of each method in the interface. There is a direct implementation //to conform to the interface, and an execute method that will call the proxied object directly //given an object and a parameter list foreach (MethodInfo interfaceMethodInfo in typeof(I).GetAllInterfaceMethods()) { //get a list of parameter types ParameterInfo[] parameterInfos = interfaceMethodInfo.GetParameters(); Type[] parameterTypes = new Type[parameterInfos.Length]; for (int i = 0; i < parameterInfos.Length; i++) { parameterTypes[i] = parameterInfos[i].ParameterType; } //get the method info of the actual object, it might have the attributes we are looking MethodInfo proxiedMethodInfo = objectToProxy.GetType().GetMethod(interfaceMethodInfo.Name, parameterTypes); //will only create proxy to call delegate if it contains the attribute we are looking for //(note that either the itnerface or the actual object we are proxing can have the attribute) //or no attribute was defined MethodBuilder proxyMethod; if (methodSelector(proxiedMethodInfo)) { MethodInfo executeMethod = typeBuilder.CreateExecuteMethod <I>(EXECUTE_PREFIX + interfaceMethodInfo.Name, interfaceMethodInfo); proxyMethod = typeBuilder.CreateProxyMethod <I>(interfaceMethodInfo, executeMethod, fieldInfo[0], fieldInfo[1]); } else { proxyMethod = typeBuilder.CreatePassThroughMethod <I>(interfaceMethodInfo, fieldInfo[0]); } //Copy accross the attributes foreach (CustomAttributeBuilder attrBuilder in CreateCustomAttributeBuilder(proxiedMethodInfo)) { proxyMethod.SetCustomAttribute(attrBuilder); } } return(typeBuilder.CreateType()); }
/// <summary> /// Creates a proxy for this object /// </summary> /// <typeparam name="I">Interface to proxy</typeparam> /// <param name="objectToProxy"></param> /// <param name="interceptorDelegate">delegate to call on method invocation</param> /// <returns></returns> public static I Proxy <I>(this I objectToProxy, EmitProxyInterceptor <I> interceptorDelegate) { return(PlatformTypeProxyCsharpHelper.Proxy <I>(objectToProxy, (info) => true, interceptorDelegate)); }