|
查看: 1109|回复: 15
|
decoupling sample
[复制链接]
|
|
|
发表于 21-12-2008 06:15 PM
|
显示全部楼层
原帖由 mokth 于 21-12-2008 05:40 PM 发表 
太HIGH LEVEL 了, 可以简单解释你的diagram 吗? 谢谢你的分享.
不好意思,功力尚浅,所以画到很烂
架设Provider[Core Web Services] 有 3 个Private Method (Method A, Method B, Method C), 和一个Public 的Method (称之为 Interface, 别误会这个Interface)
当任何一个Application (X, Y , Z) [Consumer] 要consume Provider 的任何一个Method时,是必须通过一个或多个Intermediate Web Service (Intermediate WS 只不过是跳板而已,因为Provider 和 Consumer 是没有直接的联系,而需要通过几个Server,所以Intermidiate WS 就安装在这些Server 上)
目前的做法是,Intermediate上也会有三个对应的Method (问题所在,当Provider 有新增Method, 我就得修改所有的Intermediate)
我的解决方法就是在Intermediate 里,就只有一个通用的Method. Application就只是Call这个Method (Method Param: method name & params),然后这个Method就会Call provider 的 Interface.
Interface,就根据param 上的 method name 而决定执行那个 Method, 然后把Result return 回.
希望你能够明白,我表达能力很烂   |
|
|
|
|
|
|
|
|
|
|
1. Common Solution
using System;
using System.Collections.Generic;
using System.Text;
namespace Transport.Common
{
public interface ITransport
{
void Connect();
void Disconnect();
bool SendFile(string filename);
int ReceiveFiles();
}
}
2.SMTPTransport Solution
using System;
using System.Collections.Generic;
using System.Text;
using Transport.Common;
namespace Transport
{
public class SMTP Transport
{
#region ITransport Members
public void Connect()
{
//actual implementation
Console.WriteLine("Connecting via SMTP...." ;
}
public void Disconnect()
{
//actual implementation
Console.WriteLine("Disconnecting via SMTP...." ;
}
public bool SendFile(string filename)
{
//actual implementation
Console.WriteLine("Send file {0} via SMTP....",filename);
return true;
}
public int ReceiveFiles()
{
//actual implementation
Console.WriteLine("Receiving file via SMTP...." ;
return 0;
}
#endregion
}
}
3.HTTPTransport Solution
using System;
using System.Collections.Generic;
using System.Text;
using Transport.Common;
namespace Transport
{
public class HTTP Transport
{
#region ITransport Members
public void Connect()
{
//actual implementation
Console.WriteLine("Connecting via HTTP...." ;
}
public void Disconnect()
{
//actual implementation
Console.WriteLine("Disconnecting via HTTP...." ;
}
public bool SendFile(string filename)
{
//actual implementation
Console.WriteLine("Send file {0} via HTTP....",filename);
return true;
}
public int ReceiveFiles()
{
//actual implementation
Console.WriteLine("Receiving file via HTTP...." ;
return 0;
}
#endregion
}
}
4. TransportManager Solution
using System;
using System.Collections.Generic;
using System.Text;
using Transport.Common;
using System.Reflection;
namespace Transport
{
public class TransportManager
{
public static ITransport getTransport(string transporttype)
{
ITransport trpt = null;
string classname = "Transport." + transporttype;
try
{
Type cType = Type.GetType(classname, false, true);
if (cType == null)
{
Assembly assembly = Assembly.Load(transporttype+"Transport" ;
cType = assembly.GetType(classname);
}
trpt = (ITransport)Activator.CreateInstance(cType, new object[] {});
return trpt;
}
catch (Exception ex)
{
throw new Exception("Unable to load command " + classname, ex);
}
return null;
}
}
}
5. Client
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using Transport;
using Transport.Common;
namespace Client
{
class Program
{
static void Main(string[] args)
{
string transporttype = ConfigurationManager.AppSettings["TransportType"];
ITransport trp = TransportManager.getTransport(transporttype);
trp.Connect();
trp.SendFile("Myfile.doc" ;
trp.ReceiveFiles();
trp.Disconnect();
Console.ReadKey();
}
}
}
Client.exe.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="TransportType" value="SMTP”/>
</appSettings>
</configuration>
Steps
1. Build all solutions.
2. Copy the smtptransport.dll and Httptransport.dll into client\bin\debug directory.
3. run client\bin\debug\Cleint.exe
4. Edit client\bin\debug\Cleint.exe.config file, change <add key="TransportType" value="SMTP”/> to <add key="TransportType" value="HTTP”/> , save.
5. run client\bin\debug\Cleint.exe again.
6. Create another solution call FTPTransport, include the common as reference, and implement the Itransport interface. Make sure the dll name is FTPTransport.dll.
7. Build FTPTransport solution, copy the FTPTransport.dll to client\bin\debug directory.
8. Edit client\bin\debug\Cleint.exe.config file, change <add key="TransportType" value="HTTP”/> to <add key="TransportType" value="FTP”/> , save.
9. run client\bin\debug\Cleint.exe
以上的Sample可以看出, 很容易implement新的Transport protocol而不必更改CLIENT的code.只不过是更改app.config
file而已. 而旧的transport protocol要改也一样而不必更改client的code. 留意以上的solutions,每个solution 都是INDEPENDENT 的(没有cyclic dependency).这就是decouple的好处.
|
|
|
|
|
|
|
|
|
|
|
发表于 21-12-2008 05:05 PM
|
显示全部楼层
小弟因为近期发现现用的设计在Future Enhancement & Deployment 方面有很大问题 (High Dependency), 所以重新设计过
由于Consumer 和 Provider 并不是直接连接而是要经过几个Server,所以需要Intermediate来连接
目前的设计是,如果我在Provider加了一个新的Method, 我就的修改intermediate然后从新Deploy在所有Server.
我的设计是intermediate将只有一个Common Method 来连接 Consumer & Provider

这个是我的第一个版本,不过已经修改
如果错了,不要笑我 |
|
|
|
|
|
|
|
|
|
|

楼主 |
发表于 21-12-2008 05:40 PM
|
显示全部楼层
回复 2# sfkwan 的帖子
太HIGH LEVEL 了, 可以简单解释你的diagram 吗? 谢谢你的分享.  |
|
|
|
|
|
|
|
|
|
|

楼主 |
发表于 21-12-2008 06:57 PM
|
显示全部楼层
回复 4# sfkwan 的帖子
|
明白了. 你的Intermediate Web Service 其实类似FACADE的做法. 你可以试用REFLECTION 来CALL你的PROVIDER的METHOD, 这样一来你就不用每次更改Intermediate Web Service 当你增加PROVIDER 的METHODS. |
|
|
|
|
|
|
|
|
|
|
发表于 21-12-2008 07:55 PM
|
显示全部楼层
|
|
|
|
|
|
|
|
|
|
发表于 21-12-2008 09:48 PM
|
显示全部楼层
|
|
|
|
|
|
|
|
|
|

楼主 |
发表于 22-12-2008 12:31 AM
|
显示全部楼层
回复 7# sfkwan 的帖子
你的Intermediate WS 可以试用以下的reflection 方法. 你的Consumer call 这command,
object result = RunCommand(string asemblyname,string classname,string method,object[] param);
string asemblyname = DLL name without extension (eg SMTPTransport)
string classname = Full class name (eg Tramsport.SMTP)
string method = the method u need to invoke (eg connect)
object[] param = the parameter u need to pass into the method (eg new object[] { "www.cari.com", 80} )
object result = the result of the method
//Invoke method using reflection
public object RunCommand(string asemblyname,string classname,string method,object[] param)
{
object clsinst = null;
try
{
Type cType = Type.GetType(classname, false, true);
if (cType == null)
{
Assembly assembly = Assembly.Load(asemblyname);
cType = assembly.GetType(classname);
}
clsinst = Activator.CreateInstance(cType, new object[] { });
object result = clsinst.GetType().InvokeMember(method, BindingFlags.InvokeMethod, null, clsinst, null);
return result;
}
catch (Exception ex)
{
throw new Exception("Unable to load command " + classname, ex);
}
return null;
}
如果你不想CONSUMER pass in 那些CLASSNAME 和DLL NAME, 你可以pass in 一些key,然后在Intermediate WS 同过database或XML File 来获得CLASSNAME 和DLL NAME. 哈哈,这只不过是一个简单的建议. 可能别的高手有更好的建议 
[ 本帖最后由 mokth 于 22-12-2008 12:33 AM 编辑 ] |
|
|
|
|
|
|
|
|
|
|
发表于 22-12-2008 01:24 AM
|
显示全部楼层
|
|
|
|
|
|
|
|
|
|

楼主 |
发表于 22-12-2008 12:29 PM
|
显示全部楼层
回复 10# jasonmun 的帖子
有研究过,可是SPRINT.NET还不是很成熟.在JAVA 的SPRING就很COOL.关于它的DOCUMENTATION也不多.我相信不久将来SPRINT.NET将是一个很好的FRAMEWORK.拭目以待吧.  |
|
|
|
|
|
|
|
|
|
|
发表于 22-12-2008 10:57 AM
|
显示全部楼层
有听说 Spring .NET吗 ? 听说它也支持.NET的..
前阵子, 看到有本书介绍过.. |
|
|
|
|
|
|
|
|
|
|
发表于 22-12-2008 09:43 PM
|
显示全部楼层
除了SPRING, 我也看好 NHibernate..
也是FOR .Net 的.. |
|
|
|
|
|
|
|
|
|
|

楼主 |
发表于 23-12-2008 01:35 AM
|
显示全部楼层
回复 12# jasonmun 的帖子
NHIBERNATE 是一个很不错的ORM. 我用了三年了. 还有LOG4NET 是一个很不错的LOGGING TOOL
[ 本帖最后由 mokth 于 23-12-2008 01:39 AM 编辑 ] |
|
|
|
|
|
|
|
|
|
|
发表于 23-12-2008 02:36 PM
|
显示全部楼层
|
如果不用LOAD ASSEMBLY....不是要重新DEPLOY ntermediate WS??? |
|
|
|
|
|
|
|
|
|
|

楼主 |
发表于 23-12-2008 05:04 PM
|
显示全部楼层
回复 14# aquamax 的帖子
我想是吧. 因为ntermediate WS是direct link to provider. sfkwan, 你的design,对吧?
[ 本帖最后由 mokth 于 23-12-2008 05:14 PM 编辑 ] |
|
|
|
|
|
|
|
|
|
|
发表于 23-12-2008 05:07 PM
|
显示全部楼层
原帖由 aquamax 于 23-12-2008 02:36 PM 发表 
如果不用LOAD ASSEMBLY....不是要重新DEPLOY ntermediate WS???
就是为了不要重新deploy intermediate WS, 所以想要换掉现用的设计
把Intermediate WS改成只有一个method作为连接。
大概如下 (每个Component 都在不同的 Server 而且有防火墙)
Core WS <=> Intermediate WS 1 <=> Intermediate WS 2 <=> Intermediate WS n.... <=> Application |
|
|
|
|
|
|
|
|
| |
本周最热论坛帖子
|