Source Code for Me (s-c.me)

Allows you to paste souce code to blogs! Adapted for Twitter! Here is Search Form in case you missed your code.
Tags: CSharp,DynamicServiceProxy,ServiceChannelManagerInterceptor,IInterceptor,NotSupportedException,HeaderAuthen,ProxyGenerator, Created At: 10/24/2016 8:06:53 PMViews:

HTML view:
Copy Source | Copy HTML
  1. using System.Diagnostics;
  2. using System.IO;
  3.  
  4. namespace DynamicServiceProxy
  5. {
  6.     using System.Reflection;
  7.     using System;
  8.     using System.Linq;
  9.     using System.Linq.Expressions;
  10.     using System.ServiceModel;
  11.     using Castle.DynamicProxy;
  12.  
  13.     /// <summary>
  14.     /// Класс для автоматической генерации proxy-объектов удаленных служб
  15.     /// </summary>
  16.     /// <typeparam name="TService">Контракт службы</typeparam>
  17.     public class DynamicServiceProxy<TService> where TService : class
  18.     {
  19.         /// <summary>
  20.         /// Конструктор
  21.         /// </summary>
  22.         /// <exception cref="NotSupportedException">Контракт службы не является интерфейсом или не помечен атрибутом <see cref="System.ServiceModel.ServiceContractAttribute"/></exception>
  23.         public DynamicServiceProxy()
  24.         {
  25.             var serviceType = typeof(TService);
  26.  
  27.             if (!serviceType.IsInterface || serviceType.GetCustomAttributes(typeof(ServiceContractAttribute), false).Length <=  0)
  28.             {
  29.                 throw new NotSupportedException();
  30.             }
  31.         }
  32.  
  33.         #region Параметры работы
  34.  
  35.         /// <summary>
  36.         /// Настройки защиты
  37.         /// </summary>
  38.         protected HeaderAuthen CurrentUser = new HeaderAuthen { AuthenticationKey = "string" };
  39.  
  40.         /// <summary>
  41.         /// Ссылка, где расположен сервис для вызова самый последний
  42.         /// </summary>
  43.         protected static Uri EndPointAdress = null;
  44.  
  45.         /// <summary>
  46.         /// Ссылка, где расположен сервис для вызова следующий
  47.         /// </summary>
  48.         protected static Uri NextPointAdress = null;
  49.  
  50.         /// <summary>
  51.         /// Контракт вызова
  52.         /// </summary>
  53.         protected TService _service;
  54.  
  55.         #endregion
  56.  
  57.         /// <summary>
  58.         /// Proxy-объект службы
  59.         /// </summary>
  60.         public TService Service
  61.         {
  62.             get { return _service ?? (_service = CreateServiceProxy()); }
  63.         }
  64.  
  65.  
  66.         /// <summary>
  67.         /// Генератор proxy-объектов
  68.         /// </summary>
  69.         private static readonly ProxyGenerator ProxyGenerator = new ProxyGenerator();
  70.  
  71.         /// <summary>
  72.         /// Создать proxy
  73.         /// </summary>
  74.         private static TService CreateServiceProxy()
  75.         {
  76.             return ProxyGenerator.CreateInterfaceProxyWithoutTarget<TService>(
  77.                 new ServiceChannelManagerInterceptor(NextPointAdress, EndPointAdress));
  78.         }
  79.  
  80.  
  81.         /// <summary>
  82.         /// Перехватчик вызовов для делегирования их удаленным службам
  83.         /// </summary>
  84.         class ServiceChannelManagerInterceptor : IInterceptor
  85.         {
  86.             /// <summary>
  87.             /// Ссылка, где расположен сервис для вызова самый последний
  88.             /// </summary>
  89.             private static Uri EndPointAdress;
  90.  
  91.             /// <summary>
  92.             /// Ссылка, где расположен сервис для вызова следующий
  93.             /// </summary>
  94.             private static Uri NextPointAdress;
  95.  
  96.             public ServiceChannelManagerInterceptor(Uri SD_TunnelLink, Uri SD_AdapterLink)
  97.                 : base()
  98.             {
  99.                 NextPointAdress = SD_TunnelLink;
  100.                 EndPointAdress = SD_AdapterLink;
  101.             }
  102.  
  103.             /// <summary>
  104.             /// Перехватить вызов
  105.             /// </summary>
  106.             /// <param name="invocation">Контекст вызова</param>
  107.             /// <exception cref="ActionNotSupportedException">Вызываемый метод не помечен атрибутом <see cref="System.ServiceModel.OperationContractAttribute"/></exception>
  108.             /// <exception cref="NotSupportedException">Обобщенные методы и методы с out- и ref-параметрами не поддерживаются</exception>
  109.             public void Intercept(IInvocation invocation)
  110.             {
  111.                 string DATATRANSFERNAME = "_DataTransfer";
  112.                 VerifyInvocation(invocation);
  113.                 //флаг о необходимости НЕ менять вызов
  114.                 Boolean Transparent = NextPointAdress == null ||
  115.                     String.Compare(DATATRANSFERNAME, invocation.Method.Name) ==  0;
  116.  
  117.                 MethodInfo transfer = typeof(INcbServices).GetMethod(DATATRANSFERNAME);
  118.                 //важный момент, если была вызвана функция прямого пбращения к передатчику данных, то ее не заменяем, а просто вызываем
  119.                 var invokeDelegate = Transparent
  120.                         ? CreateInvokeDelegate(invocation.Method, invocation.Arguments)
  121.                         : CreateInvokeDelegate(transfer,
  122.                                             new object[] {
  123.                                                 new HeaderAuthen
  124.                                                     {
  125.                                                       AuthenticationKey = "key"
  126.                                                     },
  127.                                                 EndPointAdress.OriginalString, //конечная точка вызова
  128.                                                 invocation.Method.Name,//конечный метод 
  129.                                                 invocation.Arguments //его параметры
  130.                                             });
  131.  
  132.                 var typeArguments = (invocation.Method.ReturnType == typeof (void))
  133.                                         ? new[] {invocation.Method.DeclaringType}
  134.                                         : new[] {invocation.Method.DeclaringType, invocation.Method.ReturnType};
  135.                 if (!Transparent)
  136.                 {
  137.                     //настройки тунельной функции
  138.                     typeArguments = new[] {transfer.DeclaringType, transfer.ReturnType};
  139.                 }
  140.                 var invokeMethod = typeof (ServiceChannelManager).FindMethod("Invoke", typeArguments,
  141.                                                                                 invokeDelegate.GetType());
  142.  
  143.                 invocation.ReturnValue = invokeMethod.Invoke(new ServiceChannelManager(NextPointAdress ?? EndPointAdress),
  144.                                                                 new[] {invokeDelegate});
  145.             }
  146.  
  147.             /// <summary>
  148.             /// Создать делегат для вызова метода
  149.             /// </summary>
  150.             private static Delegate CreateInvokeDelegate(MethodInfo tnl, object [] arguments)
  151.             {
  152.                 var lambdaParameter = Expression.Parameter(tnl.DeclaringType, "s");
  153.                 var methodArguments = (arguments != null) ? arguments.Select(a => (Expression)Expression.Constant(a)) : new Expression[] { };
  154.                 var lambdaExpression = Expression.Lambda(
  155.                     Expression.Call(lambdaParameter, tnl, methodArguments), lambdaParameter);
  156.                 return lambdaExpression.Compile();
  157.             }
  158.  
  159.             /// <summary>
  160.             /// Проверить контекст вызова
  161.             /// </summary>
  162.             /// <param name="invocation">Контекст вызова</param>
  163.             /// <exception cref="NotSupportedException"/>
  164.             /// <exception cref="ActionNotSupportedException"/>
  165.             private static void VerifyInvocation(IInvocation invocation)
  166.             {
  167.                 if (invocation.Method.GetCustomAttributes(typeof(OperationContractAttribute), false).Length <=  0)
  168.                 {
  169.                     throw new ActionNotSupportedException();
  170.                 }
  171.  
  172.                 if (invocation.GenericArguments != null || (invocation.GenericArguments != null && invocation.GenericArguments.Count() >  0)
  173.                     || invocation.Method.GetParameters().Any(p => p.IsOut || p.ParameterType.IsByRef))
  174.                 {
  175.                     throw new NotSupportedException();
  176.                 }
  177.             }
  178.         }
  179.     }
  180. }

Based on Manoli.Net's CodeFormatter. Made by Topbot (c) 2008-2018