Green.AgileMapper开源项目的使用(1)

     在架构设计中,利用领域驱动开发时,涉及到do(领域对象)和dto(数据传输对象)的相互装换匹配,这段代码简单但是重复频率太多,写得我很冒火(我有个职责是wcf SOA包装),我是个不喜欢重复劳动的懒人,我在网上搜索等到很多实体匹配的框架EmitMapper,AutoMapper等,但是他们都不能满足dto和do的对象的按规则匹配包装。最后我只得花了半个小时写了一个简单的代码生成器,完成了我的任务。但是事后总觉得不爽,于是有了写下这个AgileMapper框架来适应领域开发中的po,do,dto,vo着一些列对象的相互包装,建立一个按规则包装的Mapper框架。项目已经完成上传于CodePlexhttp://agilemapper.codeplex.com/ ,目前刚成型,希望大家能够帮助测试,提出bug,或者修复。我不是很清楚开源协议,选择了一个 协议。大家可以随便使用和修改应用来满足各自的需求,但是如果有些bug修复或者好的通用的修改希望大家能够,提交供我和其他人学习共同进步,但是这不是必须的,你也可以选择保留。

       AgileMapper架构设计类图:

    在AgileMapper中支持多种MappingConfigurator(匹配管理器)都集成至MappingConfiguratorBase(MappingConfiguratorBase中拥有唯一的对象之间对于相等的默认表达式守信,针对于dto转化为do对象级联删除情况),内置了AttributeMappingConfigurator,XMLMappingConfigurator,DataRowMappingConfigurator三种匹配管理器。支持xml书写,attribute标记规则。由这些管理器根据具体标记标记方式产生一组IMappingRule(匹配规则),内置了5中匹配规则(简单,集合,表达式,对象,datarow)。

   在AgileMapper为我们提供了MappingConfiguratorBase的扩展,IMappingRule的扩展,已经多余Attribute标注的扩展CustomerMappingAttribute,已经xml的配置扩展。

下面我们来使用AgileMapper提供的内置Mapper。

测试预备:

Domain Object:

public class StudenDo 
   { 
       public int ID 
       { 
           get; 
           set; 
       } 

       public string Name 
       { get; set; } 

       public Sex Sex 
       { get; set; } 

       public Address Address 
       { get; set; } 

       public ContactWay ContactWay 
       { get; set; } 

       public List<string> CourseIds 
       { get; set; } 

       public List<KeyValuePair> Propertys 
       { get; set; } 

   } 

   public class KeyValuePair 
   { 
       public string Key 
       { get; set; } 

       public string Value 
       { get; set; } 
   } 

   public enum Sex 
   { 
       男, 女 
   }

 

public class ContactWay 
   { 
      public string Phone 
      { 
          get; 
          set; 
      } 

      public string Email 
      { 
          get; 
          set; 
      } 

      public string QQ 
      { 
          get; 
          set; 
      } 
   }

 

 

public class Address 
   { 
       public string Country 
       { 
           get; 
           set; 
       } 

       public string Province 
       { get; set; } 

       public string Street 
       { get; set; } 

       public string Particular 
       { get; set; } 
   }

 

Dto:

  

public class StudenDto 
   { 
       public int ID 
       { 
           get; 
           set; 
       } 

       public string Name 
       { get; set; } 

       public Sex Sex 
       { get; set; } 

       [Mapping("Address.Country")] 
       public string Country 
       { 
           get; 
           set; 
       } 

       [Mapping("Address.Province")] 
       public string Province 
       { get; set; } 

       // [Mapping("Address.Street")] 
       [IgnoreMapping] 
       public string Street 
       { get; set; } 

       [ExpressionMapping("Address.Country +\" 国籍 \"+Address.Province +\" 省 \"")] 
       public string Particular 
       { get; set; } 

       [ObjectMappingAttribute] 
       public ContactWayDto ContactWay 
       { get; set; } 

       [CollectionMapping()] 
       public List<string> CourseIds 
       { get; set; } 

       [CollectionMapping(EqualExpression="from.Key==to.Key",IsDeleteNotInFromItem=true)] 
       public List<KeyValuePair> Propertys 
       { get; set; } 

       [ExpressionMapping("Propertys[0].Key")] 
       public string FirstPropertyKey 
       { 
           get; 
           set; 
       } 

 

public class ContactWayDto 
    { 
        public string Phone 
        { 
            get; 
            set; 
        } 

        public string Email 
        { 
            get; 
            set; 
        } 

        public string QQ 
        { 
            get; 
            set; 
        } 
    }

public class AddressDto 

    public string Country 
    { 
        get; 
        set; 
    } 

    public string Province 
    { get; set; } 

    public string Street 
    { get; set; } 

    public string Particular 
    { get; set; } 
}

 

一:Attribute标注:

  

[TestMethod] 
       public void AttributeConfig_SimpleMapping_Gen() 
       { 

           StudenDo stu = new StudenDo() 
           { 
               ID = 1, 
               Name = "test1", 
               Sex = Sex.女, 
               Address = new Address() 
               { 
                   Country = "中国", 
                   Province = "四川", 
                   Street = "高新区" 
               }, 
               CourseIds = new List<string>() { "1", "2", "3" }, 
               Propertys = new List<KeyValuePair>() { new KeyValuePair() { Key = "1", Value = "1" } }, 
               ContactWay = new ContactWay() 
               { 
                   Phone = "1111111111111111", 
                   Email = "xxxx@12f", 
                   QQ = "7889789999889" 
               } 
           }; 

           var mapper = ObjectMapperManager.Default.GetMapper<StudenDto, StudenDo>(); 

           var dt1 = DateTime.Now; 
           var stuDto = mapper.Warp(stu); 
           var sp = DateTime.Now - dt1; 

           dt1 = DateTime.Now; 
           stuDto = mapper.Warp(stu); 
           var sp1 = DateTime.Now - dt1; 

           Assert.AreEqual(stuDto.ID, stu.ID); 
           Assert.AreEqual(stuDto.Name, stu.Name); 
           Assert.AreEqual(stuDto.Sex, stu.Sex); 
           Assert.AreEqual(stuDto.Country, stu.Address.Country); 
           Assert.AreEqual(stuDto.Province, stu.Address.Province); 
           Assert.AreEqual(stuDto.Street, null);//Ignore 
           //object 
           // Assert.AreEqual(stuDto.ContactWay,null); 
           Assert.AreEqual(stuDto.ContactWay.QQ, stu.ContactWay.QQ); 
           Assert.AreEqual(stuDto.ContactWay.Email, stu.ContactWay.Email); 
           //expression 
           Assert.AreEqual(stuDto.Particular, string.Format("{0} 国籍 {1} 省 ", stu.Address.Country, stu.Address.Province)); 
           Assert.AreEqual(stuDto.FirstPropertyKey, stu.Propertys[0].Key); 
           //collection            
           Assert.AreEqual(stuDto.CourseIds[0], stu.CourseIds[0]); 
           Assert.AreEqual(stuDto.CourseIds.Count, stu.CourseIds.Count); 

           Assert.AreEqual(stuDto.Propertys[0].Key, stu.Propertys[0].Key); 
           Assert.AreEqual(stuDto.Propertys[0].Value, stu.Propertys[0].Value); 
           Assert.AreEqual(stuDto.Propertys.Count, stu.Propertys.Count); 

           //Warp 2 
           var stuDo = new StudenDo(); 
           mapper.Warp(stuDto, stuDo); 

           Assert.AreEqual(stuDo.ID, stuDto.ID); 
           Assert.AreEqual(stuDo.Name, stuDto.Name); 
           Assert.AreEqual(stuDo.Sex, stuDto.Sex); 
           Assert.AreEqual(stuDo.Address.Country, stuDto.Country); 
           Assert.AreEqual(stuDo.Address.Province, stuDto.Province); 
           //Assert.AreEqual(stuDo.Address.Street, null);//Ignore 
           //object 
           Assert.AreEqual(stuDo.ContactWay.QQ, stuDto.ContactWay.QQ); 
           Assert.AreEqual(stuDo.ContactWay.Email, stuDto.ContactWay.Email); 
           //collection 

           Assert.AreEqual(stuDo.CourseIds.Count, stuDto.CourseIds.Count); 
           Assert.AreEqual(stuDo.CourseIds[0], stuDto.CourseIds[0]); 

           Assert.AreEqual(stuDo.Propertys.Count, stuDto.Propertys.Count); 
           Assert.AreEqual(stuDo.Propertys[0].Key, stuDto.Propertys[0].Key); 
           Assert.AreEqual(stuDo.Propertys[0].Value, stuDto.Propertys[0].Value); 
       } 

       [TestMethod] 
       public void AttributeConfig_SimpleMapping() 
       { 
           StudenDo stu = new StudenDo() 
           { 
               ID = 1, 
               Name = "test1", 
               Sex = Sex.女, 
               Address = new Address() 
               { 
                   Country = "中国", 
                   Province = "四川", 
                   Street = "高新区" 
               }, 
               CourseIds = new List<string>() { "1", "2", "3" }, 
               Propertys = new List<KeyValuePair>() { new KeyValuePair() { Key = "1", Value = "1" } }, 
               ContactWay = new ContactWay() 
               { 
                   Phone = "1111111111111111", 
                   Email = "xxxx@12f", 
                   QQ = "7889789999889" 
               } 
           }; 

           var mapper = ObjectMapperManager.Default.GetMapper(); 
           var stuDto = mapper.Warp(typeof(StudenDto), stu) as StudenDto; 

           Assert.AreEqual(stuDto.ID, stu.ID); 
           Assert.AreEqual(stuDto.Name, stu.Name); 
           Assert.AreEqual(stuDto.Sex, stu.Sex); 
           Assert.AreEqual(stuDto.Country, stu.Address.Country); 
           Assert.AreEqual(stuDto.Province, stu.Address.Province); 
           Assert.AreEqual(stuDto.Street, null);//Ignore 
           //object 
           Assert.AreEqual(stuDto.ContactWay.QQ, stu.ContactWay.QQ); 
           Assert.AreEqual(stuDto.ContactWay.Email, stu.ContactWay.Email); 
           //expression 
           Assert.AreEqual(stuDto.Particular, string.Format("{0} 国籍 {1} 省 ", stu.Address.Country, stu.Address.Province)); 
           //collection            
           Assert.AreEqual(stuDto.CourseIds[0], stu.CourseIds[0]); 
           Assert.AreEqual(stuDto.CourseIds.Count, stu.CourseIds.Count); 
       } 

二:xml配置标注规则: 

<?xml version="1.0" encoding="utf-8" ?> 
<AgileMapper> 
  <Extensions> 
    <Extension Name="SimpleMappingRule" Type="Green.AgileMapper.SimpleMappingRule,Green.AgileMapper"></Extension> 
    <Extension Name="ObjectMappingRule" Type="Green.AgileMapper.ObjectMappingRule,Green.AgileMapper"></Extension> 
    <Extension Name="CollectionMappingRule" Type="Green.AgileMapper.CollectionMappingRule,Green.AgileMapper"></Extension> 
    <Extension Name="ExpressionMappingRule" Type="Green.AgileMapper.ExpressionMappingRule,Green.AgileMapper"></Extension> 
  </Extensions> 
  <Mappings> 
    <Mapping FromType="AgileMapper.Test.StudenDto,AgileMapper.Test"  > 
      <SimpleMappingRule FromPoperty="Country" ToPoperty="Address.Country"></SimpleMappingRule> 
      <SimpleMappingRule FromPoperty="Province" ToPoperty="Address.Province"></SimpleMappingRule>           
      <ObjectMappingRule  FromPoperty="ContactWay" ToPoperty="ContactWay"></ObjectMappingRule> 
      <CollectionMappingRule FromPoperty="CourseIds" ToPoperty="CourseIds"></CollectionMappingRule> 
      <CollectionMappingRule FromPoperty="Propertys" ToPoperty="Propertys" EqualExpression="from.Key==to.Key" IsDeleteNotInFromItem="true"></CollectionMappingRule> 
      <ExpressionMappingRule  FromPoperty="Particular" Expression="Address.Country +Address.Province"></ExpressionMappingRule> 
      <ExpressionMappingRule  FromPoperty="FirstPropertyKey" Expression="Propertys[0].Key"></ExpressionMappingRule> 
      <Ignores> 
        <Ignore Name="Street"></Ignore> 
      </Ignores> 
    </Mapping> 
  </Mappings> 
</AgileMapper>

测试代码:

  

[TestMethod] 
        public void XMlConfig_SimpleMapping_Gen() 
        { 

            StudenDo stu = new StudenDo() 
            { 
                ID = 1, 
                Name = "test1", 
                Sex = Sex.女, 
                Address = new Address() 
                { 
                    Country = "中国", 
                    Province = "四川", 
                    Street = "高新区" 
                }, 
                CourseIds = new List<string>() { "1", "2", "3" }, 
                Propertys = new List<KeyValuePair>() { new KeyValuePair() { Key = "1", Value = "1" } }, 
                ContactWay = new ContactWay() 
                { 
                    Phone = "1111111111111111", 
                    Email = "xxxx@12f", 
                    QQ = "7889789999889" 
                } 
            }; 

            var mapper = ObjectMapperManager.Default.GetMapper<StudenDto, StudenDo>(new XMLMappingConfigurator(@"E:\Project\OpenSource\AgileMapper\AgileMappper.Test\XMLConfigurator\AgileMapper.xml")); 

            var stuDto = mapper.Warp(stu);           

            Assert.AreEqual(stuDto.ID, stu.ID); 
            Assert.AreEqual(stuDto.Name, stu.Name); 
            Assert.AreEqual(stuDto.Sex, stu.Sex); 
            Assert.AreEqual(stuDto.Country, stu.Address.Country); 
            Assert.AreEqual(stuDto.Province, stu.Address.Province); 
            Assert.AreEqual(stuDto.Street, null);//Ignore 
            //object 
            // Assert.AreEqual(stuDto.ContactWay,null); 
            Assert.AreEqual(stuDto.ContactWay.QQ, stu.ContactWay.QQ); 
            Assert.AreEqual(stuDto.ContactWay.Email, stu.ContactWay.Email); 
            //expression 
            Assert.AreEqual(stuDto.Particular.Replace(" ", ""), string.Format("{0}{1}", stu.Address.Country, stu.Address.Province)); 
            Assert.AreEqual(stuDto.FirstPropertyKey, stu.Propertys[0].Key); 
            //collection            
            Assert.AreEqual(stuDto.CourseIds[0], stu.CourseIds[0]); 
            Assert.AreEqual(stuDto.CourseIds.Count, stu.CourseIds.Count); 

            Assert.AreEqual(stuDto.Propertys[0].Key, stu.Propertys[0].Key); 
            Assert.AreEqual(stuDto.Propertys[0].Value, stu.Propertys[0].Value); 
            Assert.AreEqual(stuDto.Propertys.Count, stu.Propertys.Count); 

            //Warp 2 
            var stuDo = new StudenDo(); 
            mapper.Warp(stuDto, stuDo); 

            Assert.AreEqual(stuDo.ID, stuDto.ID); 
            Assert.AreEqual(stuDo.Name, stuDto.Name); 
            Assert.AreEqual(stuDo.Sex, stuDto.Sex); 
            Assert.AreEqual(stuDo.Address.Country, stuDto.Country); 
            Assert.AreEqual(stuDo.Address.Province, stuDto.Province); 
            //Assert.AreEqual(stuDo.Address.Street, null);//Ignore 
            //object 
            Assert.AreEqual(stuDo.ContactWay.QQ, stuDto.ContactWay.QQ); 
            Assert.AreEqual(stuDo.ContactWay.Email, stuDto.ContactWay.Email); 
            //collection 

            Assert.AreEqual(stuDo.CourseIds.Count, stuDto.CourseIds.Count); 
            Assert.AreEqual(stuDo.CourseIds[0], stuDto.CourseIds[0]); 

            Assert.AreEqual(stuDo.Propertys.Count, stuDto.Propertys.Count); 
            Assert.AreEqual(stuDo.Propertys[0].Key, stuDto.Propertys[0].Key); 
            Assert.AreEqual(stuDo.Propertys[0].Value, stuDto.Propertys[0].Value); 
        }

三:DataRow的测试: 

测试预备StudentModelForDataRow:

public class StudentModelForDataRow 
    { 
        public int ID 
        { get; set; } 

        public string Name 
        { get; set; } 
    }

测试代码: 

[TestMethod] 
       public void DataRowConfig_SameTable_DataRowCloneMapping() 
       { 
           DataTable dt = new DataTable(); 
           dt.Columns.AddRange(new DataColumn[] { 
               new DataColumn("ID",typeof(int)), 
               new DataColumn("Name",typeof(string)) 
           }); 

           var row = dt.NewRow(); 
           row[0] = 1; 
           row[1] = "Green"; 
           dt.Rows.Add(row); 

           var rowClone = dt.NewRow(); 

           var mapper = ObjectMapperManager.Default.GetMapper(new DataRowMappingConfigurator()); 
           mapper.Warp(typeof(DataRow), row, rowClone); 
           Assert.AreEqual(row[0], rowClone[0]); 
           Assert.AreEqual(row[1], rowClone[1]); 
       } 

       [TestMethod] 
       public void DataRowConfig_UnSameTable_MutipleRule_DataRowCloneMapping() 
       { 
           DataTable dt = new DataTable(); 
           dt.Columns.AddRange(new DataColumn[] { 
               new DataColumn("ID",typeof(int)), 
               new DataColumn("Name",typeof(string)) 
           }); 

           DataTable dt2 = new DataTable(); 
           dt2.Columns.AddRange(new DataColumn[] { 
               new DataColumn("ID",typeof(int)), 
               new DataColumn("Name",typeof(string)), 
                new DataColumn("Sex",typeof(string)) 
           }); 

           var row = dt2.NewRow(); 
           row[0] = 1; 
           row[1] = "Green"; 
           row[2] = "Nan"; 
           dt2.Rows.Add(row); 

           var rowClone = dt.NewRow(); 

           var mapper = ObjectMapperManager.Default.GetMapper(new DataRowMappingConfigurator()); 
           mapper.Warp(row, rowClone); 
           Assert.AreEqual(row[0], rowClone[0]); 
           Assert.AreEqual(row[1], rowClone[1]); 
       } 

       [TestMethod] 
       public void DataRowConfig_UnSameTable_Not_MutipleRule_DataRowCloneMapping() 
       { 
           DataTable dt = new DataTable(); 
           dt.Columns.AddRange(new DataColumn[] { 
               new DataColumn("ID",typeof(int)), 
               new DataColumn("Name",typeof(string)) 
           }); 

           DataTable dt2 = new DataTable(); 
           dt2.Columns.AddRange(new DataColumn[] { 
               new DataColumn("ID",typeof(int)), 
               new DataColumn("Name",typeof(string)), 
                new DataColumn("Sex",typeof(string)) 
           }); 

           var row = dt.NewRow(); 
           row[0] = 1; 
           row[1] = "Green"; 
           dt.Rows.Add(row); 

           var rowClone = dt2.NewRow(); 

           var mapper = ObjectMapperManager.Default.GetMapper(new DataRowMappingConfigurator()); 
           mapper.Warp(row, rowClone); 
           Assert.AreEqual(row[0], rowClone[0]); 
           Assert.AreEqual(row[1], rowClone[1]); 
       } 

       [TestMethod] 
       public void DataRowConfig_To_Object_CloneMapping() 
       { 
           DataTable dt = new DataTable(); 
           dt.Columns.AddRange(new DataColumn[] { 
               new DataColumn("ID",typeof(int)), 
               new DataColumn("Name",typeof(string)) 
           }); 

           var row = dt.NewRow(); 
           row[0] = 1; 
           row[1] = "Green"; 
           dt.Rows.Add(row); 
           StudentModelForDataRow model = new StudentModelForDataRow(); 

           var mapper = ObjectMapperManager.Default.GetMapper(new DataRowMappingConfigurator()); 
           mapper.Warp(row, model); 
           Assert.AreEqual(model.ID, row[0]); 
           Assert.AreEqual(model.Name, row[1]); 
       }

     DataRow匹配针对相同的表结构和不同表结构,以及实体类和DataRow之间的转化。 

单元测试结果:

     对于xml配置的架构还没做,以及基于T4模板的按照规则代码生成模板还在进一步开发中,敬请期待。

     今天就写在这里了,欢迎大家的指正和修改,希望你的修改如果更好能通知我,给我好的建议和探讨,谢谢。

作者:破  狼 
出处:http://www.cnblogs.com/whitewolf/ 
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。该文章也同时发布在我的独立博客中-个人独立博客博客园--破狼51CTO--破狼。http://www.cnblogs.com/whitewolf/archive/2012/03/29/AgileMapper1.html

时间: 2024-08-27 17:19:57

Green.AgileMapper开源项目的使用(1)的相关文章

Green.AgileMapper项目(2)-新增DO和DTO代码生成

     如果你还不了解Green.AgileMapper的用意,作用请先一步到上篇Green.AgileMapper开源项目的使用,如果你觉得运行时(Runtime)的Mapper效率存在问题,在这个版本中有了更新,新增了C#直接代码的生成,这里的生成都已3.0后的扩展方法实现,你可以很方便的一句代码实现两者的转化.     代码生成我本想利用T4模板,但是由于我们的项目IDE版本是VS2008,对于T4的参数传递支持还不是很友好,你可能说用AppDomain.SetData,或者CallCo

Green.AgileMapper新增-Green.ObjectPickUper(do到dto对象的默认抽取)

     Green.AgileMapper意在处理领域驱动开发中对象之间的Mapper(如果你还不了解Green.AgileMapper,从这里开始Green.AgileMapper开源项目的使用(1) 和Green.AgileMapper项目(2)-新增DO和DTO代码生成,项目地址:CodePlexhttp://agilemapper.codeplex.com/),本项目在后期会针对领域建模提供设计时候支持,利用EF和NHibernate作为底层ORM框架产生自己的领域框架,在设计时才会采

优秀开源项目:MyXls

  主页:http://sourceforge.net/projects/myxls/  MyXls是用C#开源项目,可以应用于silverlight .asp.net 或者 .net应用程序上.它根据微软公开的Excle文档格式文件(BIFF),以二进制格式直接生成excel文档,支持Excel versions 97 - 2007. .这意味着可以不用在服务器上安装office就能够以excle格式输出数据库中存储的数据了.这对于许多项目来说都是很有用的.     目前MyXls已经实现了单

源代码-我在学习Android 的ZXing开源项目二维码时 有几个类 不清楚他具体的意义,功能。

问题描述 我在学习Android 的ZXing开源项目二维码时 有几个类 不清楚他具体的意义,功能. ①BitMatrix.java ②ByteMatrix.java ③MultiFormatWriter.java ④QRCodeWriter.java 这4个 我实在不懂 这功能,这里面哪个 是将输入字符串 变成那个0,1 那个的?用什么算法了...我这是Android工程. 谢谢了...

使用开源项目的正确姿势,都是血和泪的总结!

软件开发领域有一个流行的原则:DRY,Don't repeat yourself,我们翻译过来更形象通俗:不要重复造轮子.开源项目主要目的是共享,其实就是为了让大家不要重复造轮子,尤其是在互联网这样一个快速发展的领域,速度就是生命,引入开源项目,可以节省大量的人力和时间,大大加快业务的发展速度,何乐而不为呢?   然而现实往往没有那么美好,开源项目虽然节省了大量的人力和时间,但带来的问题也不少,相信绝大部分同学都踩过开源软件的坑,小的影响可能是宕机半小时,大的问题可能是丢失几十万数据,甚至灾难性

点评10款Github上最火爆的国产开源项目

感谢Github,让我们有了一个优秀的共享平台,享受思想碰撞.参与优秀项目的激情.下面我跟广大的程序猿们,分享一下Github上最热的10款国产开源软件(本人纯手动计算,按照星数点评,有些熟悉就说的多,不熟悉就少说.失误之处你给我指出来,我下次补上). 1. Echarts Echarts 是基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表. 所属公司:百度 Star:5204 提交时间:5/26/2013 优势:echarts提供商业产品常用

Java开源项目Hibernate快速入门

快速入门|项目   Java开源项目Hibernate快速入门其实Hibernate本身是个独立的框架,它不需要任何web server或application server的支持.然而,大多数的Hibernate入门介绍都加入了很多非Hibernate的东西,比如: Tomcat, Eclipse, Log4J,Struts, XDoclet, 甚至JBoss.这容易让人产生Hibernate复杂难懂的误解,特别是打击了初学者的积极性. 在这篇文章将不涉及Eclipse, log4j, Str

java开源项目研究 3.许可协议介绍

项目     如果你只是想学习使用一下开源项目,那么你可以跳过本节(了解一下更好^_^),但是如果你想在自己的产品(不管是开源的还是商业的)中集成开源项目,那么你必须了解许可协议.        开源项目的License可以分为三大类:     OSI-Approved Open Source:被开放源码组织(www.opensource.org)所批准的开放源码授权协议.像大家经常看到的Apache,GPL,LGPL,MIT Licence,都属于OSI-Approved的授权协议,OSI 的

java开源项目研究 2. 开源的历史

项目     提到开源,就不得不提到Richard Stallman--开源软件的始创者和精神领袖(不是偶像崇拜^_^).他是GNU(GNU's Not UNIX)工程的发起人,FSF(Free Software Foundation)的缔造者,同时还是大名鼎鼎的GNU Emacs(一个编辑工具),GCC(c/c++编译器,不用我说了吧,呵呵),GDB(调试工具)和GNU Make的作者.     Stallman的生平是和开源历史紧密相关的:     1984年,Stallman辞去了MIT