辛酸与幸福的故事,让我最近心如止水,越来越平静,越来越执着于我们的未来,越来越自信于自己的事业。

从今天开始,我每天会整理自己的文档,把自己的思路和架构思想拿出来分享,共同学习。

声明下,没有花工作的时间来写这个,一般习惯于夜深人静的时候,一边听着《财经夜读》一边总结着自己在软件领域里的知识。存档,然后定期每天一发。

其实服务层架构,是我在两年前开始研究,只是零零散散没有弄个文档出来,以下是我简要的写了下,算是关于服务架构第一篇的开题。希望有人给看法和建议,共同提高。

1 基于SOA架构思想设计
服务层有三个主要类:

Request:用户请求数据

Response:服务响应数据

以上两个类主要用于客户端的请求与响应操作。

BusinessHandler:业务处理程序

主要用于业务的父类,这是一个抽象类,用来约束业务遵循服务的规则。

服务规则

<Business>
  
<BusinessHandler type="CRM.Index;CRM" name="BH">
    
<Event name="LoadMenuTree">
      
<Request>
        
<Property type="String">UserId</Property>
        
<Property type="Menu">Menu</Property>
        
<Property type="TreeView">Tree</Property>
        
<Property type="String">Exit</Property>
      
</Request>
    
</Event>
    
<Event name="Login">
      
<Request>
        
<Property type="String">UserId</Property>
        
<Property type="String">UserPwd</Property>
        
<Property type="String">IP</Property>
      
</Request>
      
<Response>
        
<Property type="Boolean">IsLogin</Property>
        
<Property type="String">Theme</Property>
        
<Property type="String">UserName</Property>
      
</Response>
     
</Event>
  
</BusinessHandler>
</Business>

 

注意,在BusinessHandler节点里,属性type格式与持久数据层里的配置类似,用“;”隔开,前面为Class,后者为Assembly;而且Assembly有两种格式:

一是全名,这种可支持GAC

CRM,Version=1.0.4.29079,Culture=neutral,PublicKeyToken=ba9122935f80dbe7

另一种是简写格式,一般不支持GAC,要求DLL文件在BIN或当前目录下:

CRM

最后,此业务规则,配有相应的样式表,供开发人员方便阅读规则。同时如果项目逐渐稳定,可以作为内嵌到DLL里,如Zivsoft.Services.Principle.dll。

服务层拓展

有时候,弱类型对于代码改动非常不利,所以会根据业务规则自动生成服务拓展层。在这里要感谢MS面试我的那几个面试官,是他们让我对这个拓展有了兴趣。

于是,便自定义出一个Tool自动XmlToCode,代码如下:(其实这个拓展层其实将会被废弃,因为有点得不偿失,时间久了,发现并不能弥补什么。)

 Zivsoft.Services.XmlToCode
{
    internal class Property
    {
        
public string Type
        {
            
getset;
        }
        
public string Name
        {
            
getset;
        }
    }

    
/// <summary>
    
/// 
    
/// </summary>
    internal class PropertyReader
    {
        
public void Execute()
        {
            var _ht
=new Hashtable(0);
            var al 
= GetPropertyList();
            Property p;
            var sb 
= new StringBuilder();
            sb.AppendLine(
"namespace Zivsoft.Services.ServicesExt");
            sb.AppendLine(
"{");
            
for (var i = 0; i < al.Count; i++)
            {
                p 
= al[i] as Property;
                
if (p == nullcontinue;
                var type 
= p.Type.Replace("[]""");
                
if(!_ht.Contains(type))//meet the first one
                {
                    _ht.Add(type,
new List<string> {p.Name});
                }
                
else
                {
                    var pro 
= _ht[type] as List<String>;
                    
if (pro != null&&!pro.Contains(p.Name))pro.Add(p.Name);
                }
            }
            
foreach(string type in _ht.Keys)
            {
                sb.AppendLine(
"\tpublic enum E" + type);
                sb.AppendLine(
"\t{");
                var pro 
= _ht[type] as List<string>;
                
if (pro != null)
                {
                    
for (var i = 0; i < pro.Count; i++)
                    {
                        
//property
                        sb.AppendLine("\t\t" + pro[i]+',');
                    }
                }
                sb.AppendLine(
"\t}");
            }
            sb.AppendLine(
"}");
            var path 
= AppDomain.CurrentDomain.BaseDirectory + @"ServicesExt\";
            
if (!Directory.Exists(path))Directory.CreateDirectory(path);
            var fs 
= File.Create(path+"Setting.cs");
            var sw 
= new StreamWriter(fs);
            sw.WriteLine(sb.ToString());
            sw.Close();
            fs.Close();
        }

        
#region Private Methods
        
private static ArrayList GetPropertyList()
        {
            var al 
= new ArrayList();
            var load 
= new  XmlStreamReader();
            var s 
= load.ReadStream("Service.xml");
            var sr 
= new StreamReader(s);
            
while (!sr.EndOfStream)
            {
                var line 
= sr.ReadLine();
                
if (line.IndexOf("Property"== -1continue;
                var p 
= MatchLine(line);
                
if (p != null)
                {
                    al.Add(p);
                }
            }
            sr.Close();
            
return al;
        }
        
private static Property MatchLine(string line)
        {
            line
=line.Replace("<Property type=\"","").Replace("</Property>","").Replace("\t","");
            var tag =new[]{"\">"};
            var m=line.Split(tag,StringSplitOptions.RemoveEmptyEntries);
            var type 
= m[0].Trim();
            var name 
= m[1].Trim();
            
if (type == "" || name == "")
            {
                
return null;
            }
            var p 
= new Property {Name = name, Type = type};
            
return p;
        }
        
#endregion
    }
}

 

 Zivsoft.Services.XmlToCode
{
    public class SchemaExport
    {
        
public void Execute()
        {
            Outout(
"BH.cs", GetText("BH",ServiceHandler.BusinessHandlerList));
            Outout(
"DM.cs", GetText("DM", ServiceHandler.DealMethodList));
            var pReader 
= new PropertyReader();
            pReader.Execute();
        }

        
#region Private Method
        
/// <summary>
        
/// 
        
/// </summary>
        
/// <param name="csFileName"></param>
        
/// <param name="list"></param>
        
/// <returns></returns>
        private static string GetText(string csFileName, List<string> list)
        {
            var sb 
= new StringBuilder();
            sb.AppendLine(
"namespace Zivsoft.Services.ServicesExt");
            sb.AppendLine(
"{");
            sb.AppendLine(
string.Format("\tpublic sealed class {0}", csFileName));
            sb.AppendLine(
"\t{");
            IEnumerator
<string> en = list.GetEnumerator();
            
while (en.MoveNext())
            {
                sb.Append(
"\t\tpublic const string ");
                sb.AppendLine(en.Current 
+ "=\"" + en.Current + "\";");
            }
            sb.AppendLine(
"\t}");
            sb.AppendLine(
"}");
            
return sb.ToString();
        }

        
private static void Outout(string fileName, string content)
        {
            var path 
= AppDomain.CurrentDomain.BaseDirectory + @"ServicesExt\";
            
if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            var fs 
= File.Open(path+fileName, FileMode.Create);
            var sw 
= new StreamWriter(fs, Encoding.Unicode);
            sw.WriteLine(content);
            sw.Close();
            fs.Close();
        }
        
#endregion
    }
}

 

日志跟踪

日志跟踪起源于开源框架log4net,配置在学习它的思想,但在我的框架里,我融入了自己的ColorXml日志,同时也缩减了很多log4net里面的功能,这样才具它的易用性。

4.1 日志等级

所有日志分四个等级:Error > Warning > Info > Debug

以下是接口定义:

void LogError(string message, params object[] args)
void LogWarning(string message, params object[] args)
void LogInfo(string message, params object[] args)
void LogDebug(string message, params object[] args)


调用方式非常简单,举例如下:

Logger.LogError(“error”);
Logger.LogError(“failed with exception: {0}”, e);

4.2 日志文件配置

<Log level="DEBUG">
    
<LogFile enabled="false">log"log.log</LogFile>
    
<Console len="30">true</Console>
    
<XmlLog enabled="false">log"log.xml</XmlLog>
</Log>

说明:配置总体格式如上面所示,但有些参数需要在这里说明一下:

1)     LogFile默认enabledtrue,也就是说如果不指定enabled="false",文件日志不会关闭。

2)     Console默认情况下也是为true的,而且长度len默认为Int32.MaxValue,在这里我们可以设置-1或者max来获取最大值。当然实际只要你输入非自然数,都可以是最大值了。

 

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-08-11
  • 2022-12-23
  • 2021-12-09
  • 2021-04-11
  • 2021-06-20
  • 2022-12-23
猜你喜欢
  • 2021-07-27
  • 2021-12-06
  • 2021-11-17
  • 2021-12-08
  • 2021-11-25
  • 2021-05-16
  • 2022-01-27
相关资源
相似解决方案