基于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();

 

}

posted @ 2012-11-05 16:47  阿牛  阅读(991)  评论(0编辑  收藏  举报