zoukankan      html  css  js  c++  java
  • 基于AppDomain的插件开发WCF+HttpServer分布式部署(六)

    前面实现了单机程序中使用的插件框架,但如果插件以服务形式存在,并且分布在多个服务器上, 更新一次插件需要到每个服务器上进行更新,这样很不方便。这次我们在此原框架基础上,利用WCF在进程中Host一个WebService,然后管理端引用该服务后,就可以指的对被管理运算服务器进行插件更新了。

    插件管理服务:

    /// <summary>

    ///插件管理接口

    /// </summary>

    [ServiceContract]

    public interface IPluginServiceContract

    {

    [OperationContract]

    PluginItem[] List();

    [OperationContract]

    void Add(string assemblyName, string pluginUri);

    [OperationContract]

    void Remove(string assemblyName);

    }

    /// <summary>

    ///数据类

    /// </summary>

    [DataContract]

    public class PluginItem

    {

    /// <summary>

    ///程序集名称

    /// </summary>

    [DataMember]

    public string AssemblyName { get; set; }

    /// <summary>

    ///更新日期

    /// </summary>

    [DataMember]

    public DateTime UpdateTime { get; set; }

    }

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single, UseSynchronizationContext = false)]

    public class PluginServiceImpl : IPluginServiceContract

    {

    private DirectoryInfo pluginPath;

    public PluginServiceImpl(string pluginPath)

    {

    this.pluginPath = new DirectoryInfo(pluginPath);

    }

    /// <summary>

    ///枚举当前所有插件

    /// </summary>

    /// <returns></returns>

    public PluginItem[] List()

    {

    var ret = this.pluginPath.GetFiles("*.dll").ToList().ConvertAll(d =>

    new PluginItem() { AssemblyName = Path.GetFileNameWithoutExtension(d.Name), UpdateTime = d.LastWriteTime });

    return ret.ToArray();

    }

    /// <summary>

    ///添加或者更新一个插件

    /// </summary>

    /// <param name="assemblyName">程序集名称</param>

    /// <param name="pluginUri">下载最新插件程序集的URI地址 eg:http://remote.com/plugins/plugins.hello.dll </param>

    public void Add(string assemblyName, string pluginUri)

    {

    byte[] pluginContent = new System.Net.WebClient().DownloadData(pluginUri);

    if(!assemblyName.ToLower().EndsWith(".dll"))

    {

    assemblyName = string.Concat(assemblyName, ".dll");

    }

    File.WriteAllBytes(Path.Combine(pluginPath.FullName, assemblyName), pluginContent);

    }

    /// <summary>

    ///依程序集删除一个插件

    /// </summary>

    /// <param name="assemblyName">程序集名称</param>

    public void Remove(string assemblyName)

    {

    if (!assemblyName.ToLower().EndsWith(".dll"))

    {

    assemblyName = string.Concat(assemblyName, ".dll");

    }

    File.Delete(Path.Combine(pluginPath.FullName, assemblyName));

    }

    }

    /// <summary>

    ///插件WCF启动、停止类

    /// </summary>

    public class PluginService

    {

    private ServiceHost host;

    /// <summary>

    ///开始服务

    /// </summary>

    /// <param name="hostName">主机名</param>

    /// <param name="port">端口</param>

    /// <param name="pluginPath">插件目录,一定要和插件加载类配置成一样的目录</param>

    public void Start(string hostName, int port, string pluginPath = "plugins")

    {

    IPluginServiceContract serviceContract = new PluginServiceImpl(pluginPath);

    this.host = new ServiceHost(serviceContract, new UriBuilder("http", hostName, port, "pluginservice").Uri);

    var smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();

    if (smb == null)

    {

    smb = new ServiceMetadataBehavior();

    host.Description.Behaviors.Add(smb);

    }

    smb.HttpGetEnabled = true;

    smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy12;

    host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding()

    , "mex");

    host.AddServiceEndpoint(typeof(IPluginServiceContract), new BasicHttpBinding()

    , "");

    host.Open();

    }

    /// <summary>

    ///停止服务

    /// </summary>

    public void Stop()

    {

    this.host.Close();

    }

    }

    最后是管理客户端调用:

    static void Main(string[] args)

    {

    using (WebReferences.PluginServiceImpl ps = new WebReferences.PluginServiceImpl())

    {

    var list = ps.List();

    foreach (var i in list)

    {

    Console.Write("{0}, {1}", i.AssemblyName, i.UpdateTime);

    }

    Console.WriteLine("开始删除");

    Console.ReadLine();

    if (list.Length > 0)

    {

    ps.Remove(list[0].AssemblyName);

    list = ps.List();

    foreach (var i in list)

    {

    Console.Write("{0}, {1}", i.AssemblyName, i.UpdateTime);

    }

    }

    Console.WriteLine("开始部署");

    Console.ReadLine();

    System.IO.Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(),"plugins"), "Plugins.*.dll").ToList().ForEach(d =>

    {

    //http://localhost/plugins/Plugins.HelloWorld.dll

    ps.Add(Path.GetFileNameWithoutExtension(d), "http://localhost/plugins/" + Path.GetFileName(d));

    });

    list = ps.List();

    foreach (var i in list)

    {

    Console.Write("{0}, {1}", i.AssemblyName, i.UpdateTime);

    }

    }

    Console.ReadLine();

    }

  • 相关阅读:
    对于学习 ionic的同学安装的时候肯定很痛苦 get 一个小技巧
    关于Android sdk有事安装出现报Failed to fetch URL https://dl-ssl.google.com/android/repository/addons_list-2.xml错误的问题 只要两部就可以搞定
    很多同学工作了,这里呢简单说说工作中吧可能会遇到的一些事情‘
    css定位机制
    HBuilder简单操作
    前端学习方法小结
    Ajax基础讲解 1
    css hack
    jQuery自定义滚动条样式插件mCustomScrollbar 兼容IE7的方法
    ie下面兼容性问题的一些总结(转)
  • 原文地址:https://www.cnblogs.com/evlon/p/wcfplugin.html
Copyright © 2011-2022 走看看