微软MVC实现REST风格编程

1、总体来说很简单,首先新建一个MVC框架的项目,模板选择WebAPI,这样就搞定80%了。

2、WebApiConfig.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace UrlToPngWebAPI
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            config.EnableSystemDiagnosticsTracing();
        }
    }
}

3、RouteConfig.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace UrlToPngWebAPI
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}

4、请求结构
Web2PNGRequest.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Newtonsoft.Json;

namespace UrlToPngWebAPI.Models
{
    public class Web2PNGRequest
    {
        [JsonProperty]
        public String WebURL { get; set; }
        [JsonProperty]
        public String HeaderPath { get; set; }
        [JsonProperty]
        public String FooterPath { get; set; }
    }
}

5、返回结构
Web2PNGResponse.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Newtonsoft.Json;

namespace UrlToPngWebAPI.Models
{
    public class Web2PNGResponse
    {
        [JsonProperty]
        public int ErrorCode { get; set; }
        [JsonProperty]
        public String ErrorInfo { get; set; }
        [JsonProperty]
        public String PNGPath { get; set; }
    }
}

6、Controller
Url2PNGController.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Helpers;
using System.Web.Http;
using Newtonsoft.Json;
using UrlToPngCsTest;
using UrlToPngWebAPI.Models;
using UrlToPngWebAPI.Pulgins;

namespace UrlToPngWebAPI.Controllers
{
    public class Url2PNGController : ApiController
    {
        // 返回输入参数示例
        public HttpResponseMessage Get()
        {
            Web2PNGRequest req = new Web2PNGRequest();
            req.WebURL = "webURL";
            req.HeaderPath = "headerPath";
            req.FooterPath = "footerPath";

            String jsonString = JsonConvert.SerializeObject(req);
            HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent(jsonString, Encoding.GetEncoding("UTF-8"), "application/json") };
            return result;
        }

        // GET
        public HttpResponseMessage Get(String WebURL, String HeaderPath, String FooterPath)
        {
            UrlToPng4Web.InitUrlTOPng4CS();

            Web2PNGRequest req = new Web2PNGRequest();
            req.WebURL = WebURL;
            req.HeaderPath = HeaderPath;
            req.FooterPath = FooterPath;
            Web2PNGResponse rsp = UrlToPng4Web.UrlToPNG(req);
            
            String jsonString = JsonConvert.SerializeObject(rsp);
            HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent(jsonString, Encoding.GetEncoding("UTF-8"), "application/json") };
            return result;
        }

        // POST
        public HttpResponseMessage Post(Web2PNGRequest req)
        {
            UrlToPng4Web.InitUrlTOPng4CS();

            Web2PNGResponse rsp = UrlToPng4Web.UrlToPNG(req);

            String jsonString = JsonConvert.SerializeObject(rsp);
            HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent(jsonString, Encoding.GetEncoding("UTF-8"), "application/json") };
            return result;
        }
    }
}

WCF自托管服务

一般有两种方式实现:

1、通过代码设置直接实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
using WcfTest;

namespace WcfHosting
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof (SoapService)))
            {
                host.AddServiceEndpoint(typeof(ISoapService), new WSHttpBinding(), "http://127.0.0.1:1234/neohope");

                if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
                {
                    ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
                    behavior.HttpGetEnabled = true;
                    behavior.HttpGetUrl = new Uri("http://127.0.0.1:9999/neohope/metadata");
                    host.Description.Behaviors.Add(behavior);
                }

                host.Opened += delegate
                {
                    Console.WriteLine("service started, press enter to exit.");
                };
                host.Open();
                Console.Read();
            }
        }
    }
}

2、通过配置文件实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
using WcfTest;

namespace WcfHosting
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof (SoapService)))
            {
                host.Opened += delegate
                {
                    Console.WriteLine("service started, press enter to exit.");
                };
                host.Open();
                Console.Read();
            }
        }
    }
}

app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataBehavior">
          <serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:9999/neohope/metadata" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="metadataBehavior" name="WcfTest.SoapService">
        <endpoint address="http://127.0.0.9999/neohope" binding="wsHttpBinding"
                  contract="WcfTest.ISoapService" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

WCF修改SOAP命名空间

有三个地方可以修改SOAP的命名空间:

1、ServiceContract

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Web.Configuration;

namespace WcfTest
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
    [ServiceContract(Name="SoapService",Namespace="http://wcftest.neohope.org")]
    public interface ISoapService
    {
        [OperationContract]
        [WebInvoke(Method = "GET", UriTemplate = "User/Get/{uid}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        NUser GetUser(String uid);

        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "/User", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        string UpdateUser(NUser newuser);


        [OperationContract]
        [WebInvoke(Method = "PUT", UriTemplate = "/User", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        string AddUser(NUser newuser);


        [OperationContract]
        [WebInvoke(Method = "DELETE", UriTemplate = "/User", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        string DeleteUser(String uid);
    }

    [ServiceBehavior(Name = "SoapService", Namespace = "http://wcftest.neohope.org")]
    [DataContract]
    public class NUser
    {
        string uid = "";
        string uname = "";
        string usex = "";

        [DataMember]
        public String Uid
        {
            get { return uid; }
            set { uid = value; }
        }

        [DataMember]
        public string UName
        {
            get { return uname; }
            set { uname = value; }
        }

        [DataMember]
        public string USex
        {
            get { return usex; }
            set { usex = value; }
        }
    }
}

2、服务实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfTest
{
    [ServiceBehavior(Name = "SoapService", Namespace = "http://wcftest.neohope.org")]
   public class SoapService : ISoapService
    {
        static List<NUser> users = new List<NUser>();

        static SoapService()
        {
            NUser aNUser = new NUser();
            aNUser.Uid = "001";
            aNUser.UName = "张三";
            aNUser.USex = "男";
            users.Add(aNUser);
        }

        public NUser GetUser(string uid)
        {
            foreach (NUser nuser in users)
            {
                if (nuser.Uid == uid)
                {
                    return nuser;
                }
            }

            return null;
        }

        public string UpdateUser(NUser newuser)
        {
            if (newuser == null)
            {
                return "nuewuser is null";
            }

            foreach (NUser nuser in users)
            {
                if (nuser.Uid == newuser.Uid)
                {
                    nuser.UName = newuser.UName;
                    newuser.USex = nuser.USex;
                    return "User updated";
                }
            }

            return "User not found";
        }

        public string AddUser(NUser newuser)
        {
            if (newuser == null)
            {
                return "nuewuser is null";
            }

            foreach (NUser nuser in users)
            {
                if (nuser.Uid == newuser.Uid)
                {
                    nuser.UName = newuser.UName;
                    newuser.USex = nuser.USex;
                    return "User updated";
                }
            }

            users.Add(newuser);

            return "User added";
        }

        public string DeleteUser(String uid)
        {
            bool bFound = false;
            for(int i=users.Count-1;i>=0;i--)
            {
                if (users[i].Uid == uid)
                {
                    bFound = true;
                    users.RemoveAt(i);
                }
            }

            if (!bFound)
            {
                return "User Not Found";
            }
            else
            {
                return "User Deleted";
            }
        }
    }
}

3、Web.config

<?xml version="1.0"?>
<configuration>
  
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  
  <system.serviceModel>

    <services>
      <service name="WcfTest.SoapService">
        <endpoint binding="webHttpBinding" contract="WcfTest.ISoapService" bindingNamespace="http://wcftest.neohope.org"/>
      </service>
    </services>
 
    <behaviors>
      <endpointBehaviors>
      </endpointBehaviors>
      
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
  </system.webServer>
</configuration>

WCF实现REST风格编程

1、首先需要一个ServiceContract

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfTest
{
    [ServiceContract]
    public interface IRestService
    {
        [OperationContract]
        [WebInvoke(Method = "GET", UriTemplate = "User/Get/{uid}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        NUser GetUser(String uid);


        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "/User", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        string UpdateUser(NUser newuser);


        [OperationContract]
        [WebInvoke(Method = "PUT", UriTemplate = "/User", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        string AddUser(NUser newuser);


        [OperationContract]
        [WebInvoke(Method = "DELETE", UriTemplate = "/User", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        string DeleteUser(String uid);
    }

    [DataContract]
    public class NUser
    {
        string uid = "";
        string uname = "";
        string usex = "";

        [DataMember]
        public String Uid
        {
            get { return uid; }
            set { uid = value; }
        }

        [DataMember]
        public string UName
        {
            get { return uname; }
            set { uname = value; }
        }

        [DataMember]
        public string USex
        {
            get { return usex; }
            set { usex = value; }
        }
    }
}


2、然后需要实现服务

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;

namespace WcfTest
{
    public class RestService : IRestService
    {
        static List<NUser> users = new List<NUser>();

        static RestService()
        {
            NUser aNUser = new NUser();
            aNUser.Uid = "001";
            aNUser.UName = "张三";
            aNUser.USex = "男";
            users.Add(aNUser);
        }

        public NUser GetUser(string uid)
        {
            foreach (NUser nuser in users)
            {
                if (nuser.Uid == uid)
                {
                    return nuser;
                }
            }

            return null;
        }

        public string UpdateUser(NUser newuser)
        {
            if (newuser == null)
            {
                return "nuewuser is null";
            }

            foreach (NUser nuser in users)
            {
                if (nuser.Uid == newuser.Uid)
                {
                    nuser.UName = newuser.UName;
                    newuser.USex = nuser.USex;
                    return "User updated";
                }
            }

            return "User not found";
        }

        public string AddUser(NUser newuser)
        {
            if (newuser == null)
            {
                return "nuewuser is null";
            }

            foreach (NUser nuser in users)
            {
                if (nuser.Uid == newuser.Uid)
                {
                    nuser.UName = newuser.UName;
                    newuser.USex = nuser.USex;
                    return "User updated";
                }
            }

            users.Add(newuser);

            return "User added";
        }

        public string DeleteUser(String uid)
        {
            bool bFound = false;
            for(int i=users.Count-1;i>=0;i--)
            {
                if (users[i].Uid == uid)
                {
                    bFound = true;
                    users.RemoveAt(i);
                }
            }

            if (!bFound)
            {
                return "User Not Found";
            }
            else
            {
                return "User Deleted";
            }
        }
    }
}

3、修改服务的Markup

<%@ ServiceHost Language="C#" Debug="true" Service="WcfTest.RestService" CodeBehind="RestService.svc.cs" 
    Factory="System.ServiceModel.Activation.WebServiceHostFactory"%>

4、修改服务配置
添加serviceBehaviors、endpointBehaviors、service、endpoint

<?xml version="1.0"?>
<configuration>
  
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="RestSvcBehavior" name="WcfTest.RestService">
        <endpoint binding="webHttpBinding" contract="WcfTest.IRestService" address="" behaviorConfiguration="RestEPBehavior"/>
      </service>
    </services>
 
    <behaviors>
      <endpointBehaviors>
        <behavior name="RestEPBehavior">
          <webHttp />
        </behavior>
      </endpointBehaviors>
      
      <serviceBehaviors>
        <behavior name="RestSvcBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
  </system.webServer>
</configuration>

5、访问服务

http://ip:port/RestService.svc/User/Get/001

Spring通过注解加载Bean的基本原理浅析(C#版)

这第一篇,同样讲的是spring的IOC功能,是如何实现通过注解来加载Bean文件的。
这是java版本的姐妹篇,C#版本。

文章原创,转载请注明出处www.neohope.com

经过无限精简之后,整体流程为:
1、初始化bean工厂
bean工厂根据配置,加载带有指定attribute的类,并放到了Dictionary中
2、从bean工厂获取一个bean
通过bean的id,实例化一个类,并返回

需要的前置知识为:
1、spring的基本知识
2、反射

然后是源码:
1、TestAttribute.cs
这是个Attribute类,声明了一个新的注解类型,用于表示bean及bean的名字

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestAttribute
{
    [AttributeUsage(AttributeTargets.Class)]
    class TestAttribute : System.Attribute
    {
        public String Ntype { get; set; }
        public String Nname { get; set; }
        public String Nauthor { get; set; }
        public String Nversion { get; set; }
        public String Nmsg { get; set; }
    }
}

2、TestBean.cs
这是个Bean,使用了Attribute作为标识,是用于具体加载的类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestAttribute
{
    [TestAttribute(Nname = "testbean", Nauthor = "neohope", Ntype = "BEAN", Nmsg = "this is just a message", Nversion = "1.0")]
    class TestBean
    {
        public String name;
        public int age;
        public String sex;
    }
}

3、ClassPathScanner.cs
通过指定assembly名,扫描assembly下所有的类型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace TestAttribute
{
    /// <summary>
    /// The class path scanner
    /// </summary>
    class ClassPathScanner
    {
        /// <summary>
        /// Get all assemblies in current domain <see cref="System.Reflection.Assembly"/>.
        /// </summary>
        /// <returns>string set of assembly name</returns>
        public static String[] FindAllAssembliesInCurrentDomain()
        {
            List<String> result = new List<String>();
            foreach (System.Reflection.Assembly assembly in System.AppDomain.CurrentDomain.GetAssemblies())
            {
                result.Add(assembly.GetName().Name);
            }

            return result.ToArray();
        }

        /// <summary>
        /// Get all module in current assembly
        /// </summary>
        /// <returns>string set of module name</returns>
        public static String[] FindAllModuleInThisAssembly()
        {
            List<String> result = new List<String>();
            //Assembly thisAssembly = this.GetType().Assembly;
            Assembly thisAssembly = System.Reflection.Assembly.GetExecutingAssembly();
            foreach (Module item in thisAssembly.GetModules())
            {
                result.Add(item.Name);
            }

            return result.ToArray();
        }


        /// <summary>
        /// Get all type in current assembly
        /// </summary>
        /// <returns>string set of type name</returns>
        public static String[] FindAllTypeInThisAssembly()
        {
            List<String> result = new List<String>();
            //Assembly thisAssembly = this.GetType().Assembly;
            Assembly thisAssembly = System.Reflection.Assembly.GetExecutingAssembly();
            foreach (Type item in thisAssembly.GetTypes())
            {
                result.Add(item.Name); 
            }

            return result.ToArray();
        }

        /// <summary>
        /// Get all type in the assembly
        /// </summary>
        /// <param name="assemblyName">the name of the assembly</param>
        /// <returns>Type set in the assembly</returns>
        public static Type[] FindAllTypeInAssemblyByName(String assemblyName)
        {
            Assembly theAssembly = null;
            foreach (System.Reflection.Assembly assembly in System.AppDomain.CurrentDomain.GetAssemblies())
            {
                if (assembly.GetName().Name.Equals(assemblyName))
                {
                    theAssembly = assembly;
                    break;
                }
            }
            if (theAssembly == null) return new Type[] { };

            List<Type> result = new List<Type>();
            foreach (Type item in theAssembly.GetTypes())
            {
                result.Add(item);
            }

            return result.ToArray();
        }
    }
}

4、ClassAttributeScanner.cs
工厂类,初始化时,通过attribute过滤bean,并将bean的名称及type放到dictionary中
获取实例时,通过bean名称,获取type,并实例化,返回

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace TestAttribute
{
    internal class ClassAttributeScanner
    {
        /// <summary>
        /// Dictionary of bean name and bean class
        /// </summary>
        private static Dictionary<String, Type> beanDict = new Dictionary<string, Type>();

        /// <summary>
        ///  Load all bean class with attribute from package
        /// </summary>
        /// <param name="assemblyName">the name of the assembly</param>
        /// <returns></returns>
        protected static void loadBeanTypes(String assemblyName)
        {
            Type[] allTypes = ClassPathScanner.FindAllTypeInAssemblyByName(assemblyName);
            foreach (Type aType in allTypes)
            {
                Attribute attribute  = (TestAttribute)Attribute.GetCustomAttribute(aType, typeof(TestAttribute));
                if (attribute == null) continue;

                TestAttribute ta = (TestAttribute)attribute;
                String beanName = ta.Nname;
                beanDict[beanName] = aType;
            }
        }

        /// <summary>
        /// init the bean factory
        /// </summary>
        /// <param name="assemblyName">the name of the assembly</param>
        /// <returns></returns>
        public static void InitBeanFactory(String assemblyName)
        {
            loadBeanTypes(assemblyName);
        }

        public static Object GetBean(String beanName)
        {
            Type theType = beanDict[beanName];
            if (theType != null)
            {
                //return theType.Assembly.CreateInstance(theType.FullName); 
                return Activator.CreateInstance(theType);
            }
            else
            {
                return null;
            }
        }
    }
}

5、Program.cs
程序入口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestAttribute
{
    class Program
    {
        private static void Main(string[] args)
        {
            //String[] ret = ClassPathScanner.FindAllAssembliesInCurrentDomain();
            //String[] ret = ClassPathScanner.FindAllModuleInThisAssembly();
            //String[] ret = ClassPathScanner.FindAllTypeInThisAssembly();
            //foreach (string s in ret) Console.WriteLine(s);

            ClassAttributeScanner.InitBeanFactory("TestAttribute");
            TestBean bean = (TestBean)ClassAttributeScanner.GetBean("testbean");
            bean.name = "neohope";
        }
    }
}

文章原创,转载请注明出处www.neohope.com

使用ProtocolBuffer实现RPC简单示例02

接第01部分,本节用来说明C#语言的代码实现。

使用Protoc.exe生成cs代码之后,会生成两个cs文件,Client与Server都需要包含这两个文件。

首先是Server端:
1、新建一个Console项目,引用Protoc程序集中以下几个dll文件,并添加生成的CS文件
Google.Protobuf.dll
Grpc.Core.dll
System.Interactive.Async.dll

2、新建一个类MyGRPCServer,实现JustATest.IJustATest接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Com.Neohope.Protobuf.Grpc.Test;
using Grpc.Core;

namespace TestProtoBufferCliet
{
    class MyGRPCServer : JustATest.IJustATest
    {
        public Task<AddResponse> Add(AddRequest request, ServerCallContext context)
        {
            AddResponse rsp  = new AddResponse();
            rsp.C = request.A + request.B;
            return Task.FromResult(rsp);
        }

        public Task<HelloResponse> SayHelloTo(Person request, ServerCallContext context)
        {
            HelloResponse rsp = new HelloResponse();
            rsp.Rsp = "Hello " + request.Name;
            return Task.FromResult(rsp);
        }
    }
}

3、修改Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Com.Neohope.Protobuf.Grpc.Test;
using Grpc.Core;
using TestProtoBufferCliet;


namespace TestProtoBuffer
{
    class Program
    {
        static void Main(string[] args)
        {
            Server server = new Server
            {
                Services = { JustATest.BindService(new MyGRPCServer()) },
                Ports = { new ServerPort("localhost", 1900, ServerCredentials.Insecure) }
            };
            server.Start();

            
        }
    }
}

4、编译运行
其中,非托管dll要如下放置

.
│  yourprogram.exe
│  
└─nativelibs
    ├─windows_x64
    │      grpc_csharp_ext.dll
    │      
    └─windows_x86
            grpc_csharp_ext.dll
            

然后是Client端:
1、新建一个Console项目,引用Protoc程序集中以下几个dll文件,并添加生成的CS文件
Google.Protobuf.dll
Grpc.Core.dll
System.Interactive.Async.dll

2、修改Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Com.Neohope.Protobuf.Grpc.Test;
using Grpc.Core;

namespace TestProtoBufferCliet
{
    class Program
    {
        static void Main(string[] args)
        {
            Channel channel = new Channel("127.0.0.1:1900", ChannelCredentials.Insecure);
            JustATest.JustATestClient client = JustATest.NewClient(channel);

            Person p = new Person();
            p.Name = "neohope";
            p.Age = 30;
            p.Sex = Person.Types.SexType.MALE;
            HelloResponse prsp = client.SayHelloTo(p);
            Console.WriteLine(prsp.Rsp);

            AddRequest areq = new AddRequest();
            areq.A = 1;
            areq.B = 2;
            AddResponse arsp = client.Add(areq);
            Console.WriteLine(arsp.C);

            channel.ShutdownAsync().Wait();
            Console.ReadLine();
        }
    }
}

3、编译运行
其中,非托管dll要如下放置

.
│  yourprogram.exe
│  
└─nativelibs
    ├─windows_x64
    │      grpc_csharp_ext.dll
    │      
    └─windows_x86
            grpc_csharp_ext.dll
            

使用Avro实现RPC简单示例02

接第01部分,本节用来说明C#语言的代码实现。

使用avro生成cs代码之后,会生成三个cs文件,Client与Server需要分别包含这三个文件。

首先是Server端:
1、新建一个Console项目,引用Avro程序集中以下几个dll文件
Avro.dll
Avro.ipc.dll
Castle.Core.dll
log4net.dll
Newtonsoft.Json.dll

2、项目中添加生成的以下几个cs文件
JustATest.cs
Person.cs

3、新建一个类MyAvroServer,实现JustATest接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using com.neohope.avro.test;

namespace TestAvro.com.neohope.avro.test
{
    class MyAvroServer : JustATest
    {
        public override string SayHelloTo(Person person)
        {
            return "Hello " + person.name;
        }

        public override int Add(int a, int b)
        {
            return a + b;
        }
    }
}

4、修改Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using Avro.ipc;
using Avro.ipc.Specific;
using com.neohope.avro.test;
using TestAvro.com.neohope.avro.test;

namespace TestAvro
{
    class Program
    {
        static void Main(string[] args)
        {
            SpecificResponder<JustATest> responder = new SpecificResponder<JustATest>(new MyAvroServer());
            SocketServer server = new SocketServer("localhost", 1900, responder);
            server.Start();

            Console.ReadLine();

            server.Stop();
        }
    }
}

5、编译运行

然后是Client端:
1、新建一个Console项目,引用Avro程序集中以下几个dll文件
Avro.dll
Avro.ipc.dll
Castle.Core.dll
log4net.dll
Newtonsoft.Json.dll

2、项目中添加生成的以下几个cs文件
JustATestCallback.cs
JustATest.cs
Person.cs

3、修改Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Avro.ipc;
using Avro.ipc.Specific;
using com.neohope.avro.test;

namespace TestAvroClient
{
    class Program
    {
        static void Main(string[] args)
        {
            SocketTransceiver transceiver = new SocketTransceiver("localhost", 1900);
            JustATestCallback proxy = SpecificRequestor.CreateClient<JustATestCallback>(transceiver);
            
            Person person = new Person();
            person.sex = "male";
            person.name = "neohope";
            person.address = "shanghai";
            Console.WriteLine(proxy.SayHelloTo(person));
            Console.WriteLine(proxy.Add(1, 2));

            transceiver.Close();
        }
    }
}

4、编译运行

使用Thrift实现RPC简单示例02

接第01部分,本节用来说明C#语言的代码实现。

使用thrift生成cs代码之后,会生成两个cs文件,无论是Client还是Server都要包含这个文件。

首先是Server端:
1、新建一个Console项目,引用Thrift程序集中的Thrift.dll,项目中添加生成的两个cs文件。
2、新建一个类MyThriftServer,实现JustATest.Iface接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestThrift
{
    class MyThriftServer : JustATest.Iface
    {
        public string SayHelloTo(Person person)
        {
            return "Hello " + person.Name;
        }

        public int Add(int a, int b)
        {
            return a + b;
        }
    }
}

3、修改Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Thrift.Protocol;
using Thrift.Server;
using Thrift.Transport;

namespace TestThrift
{
    class Program
    {
        static void Main(string[] args)
        {
            TServerSocket serverTransport = new TServerSocket(1900, 0, false);
            JustATest.Processor processor = new JustATest.Processor(new MyThriftServer());
            TServer server = new TSimpleServer(processor, serverTransport);
            server.Serve(); 
        }
    }
}

4、编译运行

然后是Client端:
1、新建一个Console项目,引用Thrift程序集中的Thrift.dll,项目中添加生成的两个cs文件。
2、修改Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Thrift.Protocol;
using Thrift.Transport;

namespace TestThriftClient
{
    class Program
    {
        static void Main(string[] args)
        {
            TTransport transport = new TSocket("localhost", 1900); 
            TProtocol protocol = new TBinaryProtocol(transport);
            JustATest.Client client = new JustATest.Client(protocol); 
            transport.Open(); 
 
            Person p = new Person();
            p.Name="neohope";
            Console.WriteLine(client.SayHelloTo(p));
            Console.WriteLine(client.Add(1, 2));
            
            transport.Close();
        }
    }
}

3、编译运行

使用ICE实现RPC简单示例02

接第01部分,本节用来说明C#语言的代码实现。

使用slice2cs之后,会生成一个文件JustATest.cs,无论是Client还是Server都要包含这个文件。

首先是Server端:
1、新建一个Console项目,引用ICE程序集中的Ice.dll,项目中添加JustATest.cs文件。
2、新建一个类MyICETest,实现iIceTestDisp_接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ice;
using com.neohope.ice.test;

namespace TestICEServer
{
    class MyICETest : iIceTestDisp_
    {
        public override string SayHelloTo(string s, Current current__)
        {
            return "Hello " + s;
        }

        public override int Add(int a, int b, Current current__)
        {
            return a + b;
        }
    }
}

3、修改Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestICEServer
{
    class Program
    {
        static void Main(string[] args)
        {
            Ice.Communicator ic = null;

            //初使化
            ic = Ice.Util.initialize(ref args);

            //创建适配器,并指定监听端口
            Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("NeoTestAdapter", "default -p 1900");

            //绑定
            Ice.Object obj = new MyICETest();
            adapter.add(obj,Ice.Util.stringToIdentity("NeoICETest"));

            //激活适配器
            adapter.activate();

            //持续监听,直到服务关闭
            ic.waitForShutdown();

            //清理
            if (ic != null)
            {
                try
                {
                    ic.destroy();
                }
                catch (Exception e)
                {
                }
            }
        }
    }
}

4、编译运行

然后是Client端:
1、新建一个Console项目,引用ICE程序集中的Ice.dll,项目中添加JustATest.cs文件。
2、修改Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using com.neohope.ice.test;
//using JustATest;

namespace TestICE
{
    class Program
    {
        static void Main(string[] args)
        {
            Ice.Communicator ic = null;

            try
            {
                //初使化 
                ic = Ice.Util.initialize(ref args);
                Ice.ObjectPrx obj = ic.stringToProxy("NeoICETest:default -p 1900");

                //查找并获取代理接口
                iIceTestPrx client = iIceTestPrxHelper.checkedCast(obj);
                if (client == null)
                {
                    throw new ApplicationException("Invalid proxy");
                }

                //调用服务端方法
                Console.WriteLine(client.SayHelloTo("neohope"));
                Console.WriteLine(client.Add(1, 2));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                //清理
                if (ic != null)
                {
                    try
                    {
                        ic.destroy();
                    }
                    catch (Exception e)
                    {
                        Console.Error.WriteLine(e);
                    }
                }
            }
        }
    }
}

3、编译运行

PS:
1、不要乱修改id,如果要修改,必须全部修改
2、我调整了包名,不调整也可以

CSharp程序设置自动启动

using System;
using System.Text;
using Microsoft.Win32;

namespace GPJJ
{
    class XWin32Utils
    {
        private const String KEY_PATH = "SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\RUN";
        private const String VALUE_NAME = "GPJJEXE";

        public static bool isAutoRun()
        {
            RegistryKey key = Registry.LocalMachine;
            RegistryKey autorun = key.OpenSubKey(KEY_PATH, true);
            Object o = autorun.GetValue(VALUE_NAME);
            autorun.Close();

            if(o==null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        public static void SetAutoRun(String exePath)
        {
            RegistryKey key = Registry.LocalMachine;
            RegistryKey autorun = key.OpenSubKey(KEY_PATH, true);

            autorun.SetValue(VALUE_NAME, exePath, RegistryValueKind.String);
        }

        public static void RemoveAutoRun()
        {
            if(isAutoRun())
            {
                RegistryKey key = Registry.LocalMachine;
                RegistryKey autorun = key.OpenSubKey(KEY_PATH, true);
                autorun.DeleteValue(VALUE_NAME);
            }
        }
    }
}