//==============================================================
//  版权所有：深圳杰文科技
//  文件名：RemotingProxy.cs
//  版本：V1.0  
//  创建者：Jay  ( QQ： 85363208 )
//  创建时间：2017-11-28 16:18
//  创建描述：
//  修改者：
//  修改时间：
//  修改说明： 
//==============================================================

using System;
using System.Collections;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Serialization.Formatters;
using Framework.Server;

namespace Framework.RPC
{
	//[DebuggerStepThrough]
	public class RemotingProxy : IProxy
	{
		private const string ChannelName = "Jewen";

		private static bool _IsTcp = true;

		static RemotingProxy()
		{
		}

		public string Url
		{
			get;
			set;
		}

		public void Init(string url)
		{
			if (string.IsNullOrEmpty(url))
			{
				throw new Exception("请选择服务器");
			}

			this.Url = url.ToLower();
			_IsTcp = Url.StartsWith("tcp");

			IChannel[] channels = ChannelServices.RegisteredChannels;
			foreach (IChannel channel in channels)
			{
				if (channel.ChannelName == ChannelName)
				{
					ChannelServices.UnregisterChannel(channel); //注销通道。
				}
			}

			CustomServerSinkProvider customeServiceProvider = new CustomServerSinkProvider();
			CustomClientSinkProvider customClientSinkProvider = new CustomClientSinkProvider();

			BinaryClientFormatterSinkProvider binaryClient = new BinaryClientFormatterSinkProvider();
			//binaryClient.Next = customClientSinkProvider; 压缩功能有问题，暂不使用。

			if (_IsTcp) //如果是TCP协议；
			{
				TcpClientChannel tcpClientChannel = new TcpClientChannel(ChannelName, binaryClient);

				//后一个参数表示是否对调用者做安全检查。
				//注意此参数必须与客户端的ChannelServices.RegisterChannel匹配。
				//当为true时，除非Cleint与Server同在一个Windows域里，否则Client需要提供Server的一个Windows用户的账号和密码才能登录。
				ChannelServices.RegisterChannel(tcpClientChannel, false);
			}
			else if (this.Url.StartsWith("http")) //如果是http协议（soap）；
			{
				BinaryServerFormatterSinkProvider binaryServer = new BinaryServerFormatterSinkProvider();
				binaryServer.TypeFilterLevel = TypeFilterLevel.Full;
				binaryServer.Next = customeServiceProvider;
				
				IDictionary diction = new Hashtable();
				diction["port"] = 0;
				
				HttpChannel channel = new HttpChannel(diction, binaryClient, binaryServer);
				ChannelServices.RegisterChannel(channel, false);
			}
		}

		public T Create<T>() where T : new()
		{
			Type t = typeof(T);
			T obj = (T)Activator.GetObject(typeof(T), GetUrl(Url, t.Name));

			//Remoting调用拦截器。注意，此拦截器只能拦截本地客户端调用，相当于本地客户端的AOP。
			//RemotingProxyInterceptor myProxy = new RemotingProxyInterceptor(typeof(T), GetUrl(Url, t.Name));
			//T obj = (T)myProxy.GetTransparentProxy();

			return obj;
		}

		private static string GetUrl(string url, string typeName)
		{
			if (string.IsNullOrEmpty(url))
			{
				throw new Exception("ServerUrl没有定义");
			}
			if (!url.EndsWith("/"))
			{
				url = url + "/";
			}

			if (_IsTcp)
			{
				return string.Format(url + typeName, typeName);
			}
			else
			{
				return url + typeName + ".soap";
			}
		}

	}
}
