1.运行安装文件,执行安装
安装后,因为默认安装的是针对英文版的VS2008,安装文件夹为1033,但是中文VS2008的安装文件夹为2052,因此需要将1033文件夹改名或将内容拷贝到2052文件夹下
具体步骤如下:
1.将C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplates\Web\MVC\1033
C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplatesCache\Web\MVC\1033
文件夹改名为2052
2.将C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\Test\1033
C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\Web\1033
C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplatesCache\Test\1033
C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplatesCache\Web\1033
拷贝到对应路径下的2052文件夹中
记得一定要将Test文件夹下的1033内容拷贝到2052中,否则创建项目时不会创建测试项目。
[软件]VS2008Team版序列号
VS2008破解方法非常简单,在开始>设置>控制面版>添加或删除程序>卸载vs.net2008>出现卸载界面>点击Next>输入上面CD-key ->出现成功画面即可完美将试用版升级成为正式版。
VS2008正式版序列号CDKEY:PYHYP-WXB3B-B2CCM-V9DX9-VDY8T
[教程]ASP.NET AJAX (Atlas) 拖放(Drag & Drop)功能6种实现
在Ajax程序中实现传统桌面程序中异常简单的拖放功能却并不是件容易的事情。然而Web上的拖放功能又如此的让人痴迷,所以几乎每个成熟的 Ajax类库都提供了自己的一套实现拖放的封装,ASP.NET AJAX (Atlas) 自然也不例外。本文将总结并简要分析ASP.NET AJAX (Atlas) 中拖放功能的6种不同的实现方法,希望能够帮助朋友们选出最适合实际需求的方法。
其中第1到第4种方案,在我 的《ASP.NET Ajax程序设计——第I卷:服务器端ASP.NET 2.0 AJAX Extensions与ASP.NET AJAX Control Toolkit》一书中有详细介绍(4月出版),本文中的代码和图示也节选自该书。第5第6种方案,在我的《ASP.NET 2.0 Ajax程序设计——第II卷:客户端Microsoft AJAX Library》一书中将有详细介绍(暂定7月出版)。
不过纵观这些解决方案,我很遗憾的发现,要么是使用简单,可定制能力差,要么就是可定制能力强,但使用起来要写很多代码。希望ASP.NET AJAX (Atlas) 团队能够再接再厉,努力把这个重要功能做得更好。或者我有哪种方法漏掉了,也请朋友们帮忙补充一下。
[1] 使用服务器端DragOverlayExtender或客户端DragOverlayBehavior
服务器端的DragOverlayExtender就是靠着客户端DragOverlayBehavior而实现的,前者是后者在服务器端的组件化封装,所以我们将二者放在一起讨论。
这 个“拖放”功能很简单,其实这只是个“拖拽”,而没有“投放”。也就是说,你可以随意将某个Panel在页面中拖来拖去,不过却没有什么固定的地方可以 “投放”,就像在Windows桌面上拖放某个窗口的位置一样——其实用处不大,也没有提供什么可定制能力。但它使用起来非常简单,也支持将Panel的 位置保存在Profile中。
下面是一段DragOverlayExtender的示例代码,至于DragOverlayBehavior的用法,请查看DragOverlayExtender页面生成的HTML代码:
<asp:Login ID="floatLogin" BackColor="white"
BorderStyle="Solid" BorderColor="black"
runat="server">
</asp:Login>
<asp:DragOverlayExtender ID="DragOverlayExtender2"
Enabled="true" TargetControlID="floatLogin"
runat="server" />
效果如下:

[2] 使用服务器端DragPanel
DragPanel是ASP.NET AJAX Control Toolkit中的一个扩展器控件。其功能基本与DragOverlayExtender和DragOverlayBehavior一样,且同样可以保存 Panel的位置信息至Profile中。不同之处在于,DragOverlayExtender和DragOverlayBehavior的拖拽实现方 式中,鼠标放在整个Panel的任何部分都可以开始拖拽,而DragPanel在进行拖拽时,只有鼠标放在指定的DragHandle(类似于 Windows窗口的标题栏部分)中才能开始拖拽。
对于DragHandle的扩展性和实用性,同样不敢恭维。
下面是一段示例代码:
<asp:Panel ID="floatPanel" CssClass="floatPanel" runat="server">
<asp:Panel ID="floatPanelHandle" CssClass="handle" runat="server">
窗口的拖动
</asp:Panel>
<div class="content">
在Windows中,对窗口的拖动似乎成了我们习以为常的事情。
………………
………………
Window窗口的表现行为一样。
</div>
</asp:Panel>
<ajaxToolkit:DragPanelExtender ID="dpe" TargetControlID="floatPanel"
DragHandleID="floatPanelHandle" runat="server">
</ajaxToolkit:DragPanelExtender>
效果如下:

[3] 使用服务器端ReorderList
ASP.NET AJAX Control Toolkit中的ReorderList控件将在页面中呈现出一个由数据绑定自动生成的条目列表。用户可以通过鼠标拖动某一项来直接改变该列表中条目彼 此之间的相对位置关系,且在拖动的过程中,ReorderList控件提供了丰富的、可定制的视觉效果。当用户在某个位置放开鼠标之后, ReorderList控件也将同样会自动通知与其绑定的数据源控件,以Ajax的异步或整页回送的同步方式更新服务器端数据。
ReorderList控件的使用比较简单(服务器端控件),功能也相当的丰富,扩展能力也不错。不过仍称不上最灵活,比如我们想把条目在多个ReorderList之间拖放,那么就没办法实现了——因此,不要指望它能实现WebPart那样的功能。
下面是一段示例代码:
<ajaxToolkit:ReorderList ID="musicList" CssClass="musicList"
DragHandleAlignment="Left" PostBackOnReorder="false"
DataSourceID="musicDataSource" DataKeyField="Id"
SortOrderField="Order" runat="server">
<ItemTemplate>
<ajaxToolkit:Rating ID="rating" runat="server"
CssClass="rating" StarCssClass="ratingStar"
FilledStarCssClass="filledRatingStar" EmptyStarCssClass="emptyRatingStar"
CurrentRating='<%# Bind("Rating") %>' MaxRating="5"
ReadOnly="true">
</ajaxToolkit:Rating>
</ItemTemplate>
<ReorderTemplate>
<div class="dragDue">
Drop Here!
</div>
</ReorderTemplate>
<DragHandleTemplate>
<asp:Label ID="lbTitle" CssClass="dragHandle"
ToolTip="Drag Me!" runat="server" Text='<%# Bind("Name") %>'>
</asp:Label>
</DragHandleTemplate>
</ajaxToolkit:ReorderList>
效果挺酷的:

[4] 使用UpdatePanel与ASP.NET AJAX中的新版本WebPart控件
ASP.NET 2.0中的WebPart相关的控件虽然非常丰富,易于使用且功能强大,我们在程序中也很需要它所提供的拖拽功能,但它却存在着两个致命的缺陷:
- 拖放功能只支持IE浏览器。
- 每次用户通过拖放改变配件的位置之后,页面总会自动进行回送以保存当前的设定。
其中第一个问题可以通过ASP.NET AJAX中的新版本WebPart控件搞定,第二个问题可以通过添加UpdatePanel搞定,本来在CTP版本中的ASP.NET AJAX里面,这些功能均已经完美实现了。谁知道在最新的Futures CTP中,却又不好用了。
既然现在已经不能用了,也就没必要分析其优点缺点了。不过还是给出一张截图吧,缅怀一下曾经的辉煌(注意,这可是在Firefox中啊!)……

[5] 使用客户端DragDropList
DragDropList定义于ASP.NET AJAX Futures CTP中,功能非常强大,且全部在客户端实现,给服务器端减轻了不少的压力。使用DragDropList实现第4种解决方案中的WebPart类似的效 果完全没有问题,不过唯一让人感到遗憾的就是,其扩展功能不是很好,用户虽然可以随便将某个Panel从一个区域拖到另一个区域,但拖拽的结果却很难持久 化下来……且使用起来也不是那么的容易,效率上更是不敢恭维……总之,这是个很让人矛盾的东西,有些鸡肋的感觉。
我曾经在《使用ASP.NET Atlas实现拖放(Drag & Drop)效果(下)》这篇文章中给出过DragDropList的示例程序,虽然是基于CTP版本的ASP.NET AJAX ,不过实际上并不需要多少修改就能运行于最新版本之上。感兴趣的朋友可以看看,也可以到官方论坛上搜索一下相关的主题。
[6] 在客户端自行实现IDragSource和IDropTarget接口
来到了这个解决方案,可以说你对ASP.NET AJAX中的拖拽实现有了一个较深入的了解。上面的DragDropList其实就是实现了IDragSource和IDropTarget接口,其中前 者用来定义可以被拖拽的项目,后者用来定义可以被投放的区域。详细理论上的说明,可以参考我的文章《使用ASP.NET Atlas实现拖放(Drag & Drop)效果(上)》,虽然目前已经有所变化,不过仍可以参考。
这种实现方案应该说是最为强大的了,想要什么功能,肯定都能实现。不过实际开发中的难度也不小——甚至可以说是相当复杂,Jeff Prosise的这篇文章《Implementing Drag-Drop in ASP.NET AJAX》给出了一个非常简单的示例程序,感兴趣想要学习的朋友不妨看看……
[教程]C#的反射机制实例
[教程]如何用C#实现依赖注入?
1. 问题的提出
开发中,尤其是大型项目的开发中,为了降低模块间、类间的耦合关系,比较提 倡基于接口开发,但在实现中也必须面临最终是“谁”提供实体类的问题。Martin Fowler在《Inversion of Control Containers and the Dependency Injection pattern》中也提到了标准的三种实现方式——Constructor Injection、Setter Injection和Interface Injection,很全面的阐释了这个问题。
对于C#而言,由于语法元素上本身要比Java丰富,如何实施注入还有些技巧和特色之处。这方面微软的ObjectBuilder是个不错的教科书,对三种标准方式的实现也都很到位,但就是有些庞大了。
本文中,笔者借鉴Martin Fowler的撰文,也通过一些精简的代码片断向读者介绍C#实现依赖注入的基本技巧。
我有个习惯,每天晚上要看天气预报,就以这个开始好了,先定义待注入对象的抽象行为描述,然后增加一个假的实体类,相关代码和单元测试如下:

C#
using System;
namespace VisionLogic.Training.DependencyInjection.Scenario
{
/// <summary>
/// 抽象注入对象接口
/// </summary>
public interface IWeatherReader
{
string Current { get;}
}
}
C#
using System;
namespace VisionLogic.Training.DependencyInjection.Scenario.Raw
{
/// <summary>
/// 伪造的一个实现类
/// </summary>
class FakeWeatherReader : IWeatherReader
{
public string Current { get { return string.Empty; } }
}
/// <summary>
/// 客户程序
/// </summary>
public class Client
{
protected IWeatherReader reader = new FakeWeatherReader();
public virtual string Weather
{
get
{
string current = reader.Current;
switch (current)
{
case "s": return "sunny";
case "r": return "rainy";
case "c": return "cloudy";
default:
return "unknown";
}
}
}
}
}
Unit Test
using Microsoft.VisualStudio.TestTools.UnitTesting;
using VisionLogic.Training.DependencyInjection.Scenario;
using VisionLogic.Training.DependencyInjection.Scenario.Raw;
namespace VisionLogic.Training.DependencyInjection.Scenario.UnitTest.Raw
{
[TestClass]
public class WeatherReaderTest
{
[TestMethod]
public void Test()
{
Client client = new Client();
Assert.AreEqual<string>("unknown", client.Weather);
}
}
}
问题就出现了,虽然美好的愿望是Client仅仅依赖抽象的IWeatherReader,但之前总要和一个实体类“轧”一道,那么实际的效果就是实体类 作了修改、重新编译了,Client也要处理,没有真正达到隔离的目的。依赖注入通过引入第三方责任者的方法,相对好的梳理了这个关系,这位重要的角色就 是一个Assembler类,他和实体类型打交道,对Client而言他总是可以根据约定,加工出需要的IWeatherReader。

2.进一步的分析
看上去,Client被解放了,但又套住了Assembler,为了尽量让他与实体类间松散些需要做什么呢?
首先要完成自己的职责:可以找到合适的实现类实例,不管是重新构造一个还是找个现成的。
既要根据需要加工接口IWeatherReader,又要让自己尽量不与大量的实体类纠缠在一起,最好的办法就是从.Net Framework中再找到一个“第三方”,这里选中了System.Activator。
还有就是当客户程序调用Assembler的时候,它需要知道需要通过哪个实现类的实例返回,该项工作一方面可以通过一个字典完成,也可以通过配置解决,两者应用都很普遍,怎么选择呢——抽象,提取一个接口,然后都实现。
由于本文主要介绍依赖注入的实现,为了简单起见,采用一个伪造的内存字典方式,而非基于System.Configuration的配置系统实现一个Assembler的协同类。

C# 新增一个用于管理抽象类型——实体类型映射关系的类型ITypeMap
using System;
using System.Collections.Generic;
namespace VisionLogic.Training.DependencyInjection.Scenario
{
/// <summary>
/// 考虑到某些类型没有无参的构造函数,增加了描述构造信息的专门结构
/// </summary>
public class TypeConstructor
{
private Type type;
private object[] constructorParameters;
public TypeConstructor(Type type, params object[] constructorParameters)
{
this.type = type;
this.constructorParameters = constructorParameters;
}
public TypeConstructor(Type type) : this(type, null) { }
public Type Type { get { return type; } }
public object[] ConstructorParameters { get { return constructorParameters; } }
}
/// <summary>
/// 管理抽象类型与实体类型的字典类型
/// </summary>
public interface ITypeMap
{
TypeConstructor this[Type target]{get;}
}
}
C# 实现一个Assembler类型,为了示例方便,同时实现了一个ITypeMap和IWeatherReader
using System;
using System.Collections.Generic;
namespace VisionLogic.Training.DependencyInjection.Scenario
{
/// <summary>
/// 测试用的实体类
/// </summary>
public class WeatherReaderImpl : IWeatherReader
{
private string weather;
public WeatherReaderImpl(string weather)
{
this.weather = weather;
}
public string Current
{
get { return weather; }
}
}
/// <summary>
/// 管理抽象类型与实际实体类型映射关系,实际工程中应该从配置系统、参数系统获得。
/// 这里为了示例方便,采用了一个纯内存字典的方式。
/// </summary>
public class MemoryTypeMap : ITypeMap
{
private Dictionary<Type, TypeConstructor> dictionary =
new Dictionary<Type, TypeConstructor>();
public static readonly ITypeMap Instance;
/// <summary>
/// Singleton
/// </summary>
private MemoryTypeMap(){}
static MemoryTypeMap()
{
MemoryTypeMap singleton = new MemoryTypeMap();
// 注册抽象类型需要使用的实体类型
// 该类型实体具有构造参数,实际的配置信息可以从外层机制获得。
singleton.dictionary.Add(typeof(IWeatherReader), new TypeConstructor(
typeof(WeatherReaderImpl), "s"));
Instance = singleton;
}
/// <summary>
/// 根据注册的目标抽象类型,返回一个实体类型及其构造参数数组
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public TypeConstructor this[Type type]
{
get
{
TypeConstructor result;
if (!dictionary.TryGetValue(type, out result))
return null;
else
return result;
}
}
}
public class Assembler<T>
where T : class
{
/// <summary>
/// 其实TypeMap工程上本身就是个需要注入的类型,可以通过访问配置系统获得,
/// 这里为了示例的方便,手工配置了一些类型映射信息。
/// </summary>
private static ITypeMap map = MemoryTypeMap.Instance;
public T Create()
{
TypeConstructor constructor = map[typeof(T)];
if (constructor != null)
{
if (constructor.ConstructorParameters == null)
return (T)Activator.CreateInstance(constructor.Type);
else
return (T)Activator.CreateInstance(
constructor.Type, constructor.ConstructorParameters);
}
else
return null;
}
}
}
Unit Test
using Microsoft.VisualStudio.TestTools.UnitTesting;
using VisionLogic.Training.DependencyInjection.Scenario;
namespace VisionLogic.Training.DependencyInjection.Scenario.UnitTest
{
[TestClass()]
public class AssemblerTest
{
[TestMethod]
public void Test()
{
IWeatherReader reader = new Assembler<IWeatherReader>().Create();
Assert.IsNotNull(reader);
Assert.AreEqual<System.Type>(typeof(WeatherReaderImpl), reader.GetType());
}
}
}
3.经典方式下的注入实现
在完成了Assembler这个基础环境后,就是怎么注入的问题了,下面是对三种方式的经典方法实现:
3.1 Constructor Injection方式
Unit Test – Constructor
using Microsoft.VisualStudio.TestTools.UnitTesting;
using VisionLogic.Training.DependencyInjection.Scenario;
namespace VisionLogic.Training.DependencyInjection.Scenario.UnitTest
{
[TestClass]
public class ConstructorInjectionTest
{
class Client
{
private IWeatherReader reader;
public Client(IWeatherReader reader)
{
this.reader = reader;
}
}
[TestMethod]
public void Test()
{
IWeatherReader reader = new Assembler<IWeatherReader>().Create();
Client client = new Client(reader);
Assert.IsNotNull(client);
}
}
}
3.2 Setter Injection方式
Unit Test – Setter
using Microsoft.VisualStudio.TestTools.UnitTesting;
using VisionLogic.Training.DependencyInjection.Scenario;
namespace VisionLogic.Training.DependencyInjection.Scenario.UnitTest
{
[TestClass]
public class SetterInjectionTest
{
class Client
{
private IWeatherReader reader;
public IWeatherReader Reader
{
get { return reader; }
set { reader = value; }
}
}
[TestMethod]
public void Test()
{
IWeatherReader reader = new Assembler<IWeatherReader>().Create();
Client client = new Client();
client.Reader = reader;
Assert.IsNotNull(client.Reader);
}
}
}
3.3 Interface Injection方式
Unit Test – Interface
using Microsoft.VisualStudio.TestTools.UnitTesting;
using VisionLogic.Training.DependencyInjection.Scenario;
namespace VisionLogic.Training.DependencyInjection.Scenario.UnitTest
{
[TestClass]
public class InterfaceInjectionTest
{
interface IClientWithWeatherReader
{
IWeatherReader Reader { get; set;}
}
class Client : IClientWithWeatherReader
{
private IWeatherReader reader;
#region IClientWithWeatherReader Members
public IWeatherReader Reader
{
get { return reader; }
set { reader = value; }
}
#endregion
}
[TestMethod]
public void Test()
{
IWeatherReader reader = new Assembler<IWeatherReader>().Create();
Client client = new Client();
IClientWithWeatherReader clientWithReader = client;
clientWithReader.Reader = reader;
Assert.IsNotNull(clientWithReader.Reader);
}
}
}
4. 用属性(Attribute)注入
C#还可以通过Attribute注入,Enterprise Library中大量使用这种方式将各种第三方机制加入到类系统中。例如:
•运行监控需要的Performance Counter。
•用于构造过程的指标信息。
•用于日志、密码处理。
•等等
注:Java语言虽然发展比较慢,但在Java 5种也提供了类似的Annotation的机制,换了个名字省去被评估为“抄袭”的嫌疑。)
为了演示方便,下面设计一个应用情景:
Scenario
1、 应用需要一个集中的机制了解系统中实际创建过多少个特定类型对象的实例,用于评估系统的Capacity要求。
2、 为了防止系统资源被用尽,需要控制每类对象实例数量。
怎么实现呢?如下:
•增加一个内存的注册器,登记每个类已经创建过的实例实例数量。
•然后给每个类贴个标签——Attribute,让Assembler在生成的对象的时候根据标签的内容把把登记到注册器。
4.1定义抽象业务实体
C#
using System;
namespace VisionLogic.Training.DependencyInjection.Scenario.Attributer
{
/// <summary>
/// 抽象的处理对象
/// </summary>
public interface IObjectWithGuid
{
string Guid { get; set;}
}
}
定义需要注入的限制接口,并用一个Attribute管理它
C#
using System;
namespace VisionLogic.Training.DependencyInjection.Scenario.Attributer
{
/// <summary>
/// 需要注入的用以限制最大数量的接口
/// </summary>
public interface ICapacityConstraint
{
int Max { get;}
}
public class CapacityConstraint : ICapacityConstraint
{
private int max;
public CapacityConstraint(){this.max = 0;} // 默认情况下不限制
public CapacityConstraint(int max) { this.max = max; }
public int Max { get { return max; } }
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ConstraintAttribute : Attribute
{
private ICapacityConstraint capacity;
public ConstraintAttribute(int max) { this.capacity = new CapacityConstraint(max); }
public ConstraintAttribute() { this.capacity = null; }
public ICapacityConstraint Capacity { get { return capacity; } }
}
}
Assembler上增加通过Attribute注入限制的响应
C#
using System;
using System.Collections.Generic;
namespace VisionLogic.Training.DependencyInjection.Scenario.Attributer
{
public class Assembler
{
/// <summary>
/// 登记相关类型对“最大容量”属性的使用情况
/// </summary>
private IDictionary<Type, ConstraintAttribute> attributeRegistry =
new Dictionary<Type, ConstraintAttribute>();
/// <summary>
/// 登记每个类型(如须受到“最大容量”属性限制的话),实际已经创建的对象数量
/// </summary>
private IDictionary<Type, int> usageRegistry = new Dictionary<Type, int>();
public T Create<T>()
where T : IObjectWithGuid, new()
{
ICapacityConstraint constraint = GetAttributeDefinedMax(typeof(T));
if ((constraint == null) || (constraint.Max <= 0)) // max <= 0 代表是不需要限制数量的。
return InternalCreate<T>();
else
{
if (usageRegistry[typeof(T)] < constraint.Max) // 检查是否超出容量限制
{
usageRegistry[typeof(T)]++; // 更新使用情况注册信息
return InternalCreate<T>();
}
else
return default(T);
}
}
// helper method
// 直接生成特定实例,并setter 方式注入其guid。
private T InternalCreate<T>()
where T : IObjectWithGuid, new()
{
T result = new T();
result.Guid = Guid.NewGuid().ToString();
return result;
}
/// helper method.
// 获取特定类型所定义的最大数量, 同时视情况维护attributeRegistry 和usageRegistry 的注册信息。
private ICapacityConstraint GetAttributeDefinedMax(Type type)
{
ConstraintAttribute attribute = null;
if (!attributeRegistry.TryGetValue(type, out attribute)) //新的待创建的类型
{
// 填充相关类型的“最大容量”属性注册信息
object[] attributes = type.GetCustomAttributes(typeof(ConstraintAttribute), false);
if ((attributes == null) || (attributes.Length <= 0))
attributeRegistry.Add(type, null);
else
{
attribute = (ConstraintAttribute)attributes[0];
attributeRegistry.Add(type, attribute);
usageRegistry.Add(type, 0); // 同时补充该类型的使用情况注册信息
}
}
if (attribute == null)
return null;
else
return attribute.Capacity;
}
}
}
4.2对方案的测试
C#
using Microsoft.VisualStudio.TestTools.UnitTesting;
using VisionLogic.Training.DependencyInjection.Scenario.Attributer;
namespace VisionLogic.Training.DependencyInjection.Scenario.UnitTest.Attributer
{
[TestClass()]
public class AssemblerTest
{
public abstract class ObjectWithGuidBase : IObjectWithGuid
{
protected string guid;
public virtual string Guid
{
get { return guid; }
set { guid = value; }
}
}
[Constraint(2)] // 通过属性注入限制
public class ObjectWithGuidImplA : ObjectWithGuidBase { }
[Constraint(0)] // 通过属性注入限制
public class ObjectWithGuidImplB : ObjectWithGuidBase { }
[Constraint(-5)] // 通过属性注入限制
public class ObjectWithGuidImplC : ObjectWithGuidBase { }
public class ObjectWithGuidImplD : ObjectWithGuidBase { }
[TestMethod]
public void Test()
{
Assembler assembler = new Assembler();
for (int i = 0; i < 2; i++)
Assert.IsNotNull(assembler.Create<ObjectWithGuidImplA>());
Assert.IsNull(assembler.Create<ObjectWithGuidImplA>()); // 最多两个
for (int i = 0; i < 100; i++)
Assert.IsNotNull(assembler.Create<ObjectWithGuidImplB>()); // 不限制
for (int i = 0; i < 100; i++)
Assert.IsNotNull(assembler.Create<ObjectWithGuidImplC>()); // 不限制
for (int i = 0; i < 100; i++)
Assert.IsNotNull(assembler.Create<ObjectWithGuidImplD>()); // 不限制
}
}
}
5. 进一步讨论
上面的例子虽然仅仅通过Attribute注入了一个容量限制接口,但完全可以为他增加一个容器,可以把一组限制接口借助ConstraintAttribute这个通道注入进去,并在Assembler中生效。
6.其他问题
实际项目中,为了满足多核系统的需要,Assembler往往和目标对象分别运行在主进程和具体某个线程之中,如何线程安全的注入是必须面临并谨慎设计的问题。
[教程]C#的反射机制
何为反射?
反射指的是一个编程技巧,在当前应用领域的运行时间内,开发者可以利用它授权一个程序集检查并修改自身或其他程序集。那些检查能够让开发者执行比用其他方 法实现的更为强大的后期捆绑功能。反射是一个较新的微软开发方法;但是,Java和其他现代语言包含了与之十分相似的功能。作为.NET Framework的一项特色,反射能够被任何与.NET兼容的语言应用,如C#、VB.NET或J#。与本文的可下载版本一同的C#样本项目说明了本文 介绍的一些技巧。
反射的运作模式?
.NET Framework中生成的每个程序集都包含了描述程序集以及程序集中的类或结构的元数据。应用这个元数据,反射能够列举一个程序集所包含的一切类、结构和数据。一旦我们了解某一程序集的功能,就可能修改并利用这些功能。
为说明反射如何应用元数据,仔细研究下面从样本C#项目中摘录的代码。
private string ListProperties(object objectToInspect) { string returnString = ""; //To use reflection on an object, you // first need to get an instance // of that object's type. Type objectType = objectToInspect.GetType(); //After you have the object's type, you can get![]()
// information on that type. In this case, we're
![]()
// asking the type to tell us all the
![]()
// properties that it contains.
![]()
PropertyInfo[] properties =
![]()
objectType.GetProperties();
![]()
//You can then use the PropertyInfo array
![]()
// to loop through each property of the type.
![]()
foreach(PropertyInfo property in properties)
![]()
{
![]()
//The interest part of this code
![]()
// is the GetValue method. This method
![]()
// returns the value of the property.
![]()
returnString += property.Name + ": " +
![]()
property.GetValue(objectToInspect, null) +
![]()
"\r\n"; }
return returnString; }
在这段代码中,我们列举了一个类包含的属性。为完成这一点,反射应用程序集中的元数据返回一个包含类中的属性的PropertyInfo数组。然后我们循环遍历PropertyInfo数组,并单独访问每个属性。
在应用反射时,阅读元数据的过程对开发者是开放的。但是,反射应用元数据这一事实是重点。
应用反射
反射可用来执行一系列的功能。大多数的序列化引擎应用反射从需要序列化的对象中提取数据。反射还可以用内置模块来建立可自定义的应用结构。许多对象关系建模(ORM)还利用反射来执行动态映射功能。
虽然没有进行广泛宣传,反射的最有趣应用之一在于它能大大减少完成单调开发任务所需的时间。由于反射是完全动态的,它允许你在不必重新生成代码的情况下改变基本的结构,因而反射是一个非常优秀的代码生成替代工具。
例如,许多代码生成工具允许你根据基本的数据库建立数据对象。反射可用来从DataTables——它由数据库中返回——这样的数据结构中动态提取商业对 象(类)。应用这种方法,就不必应用代码生成器来生成代码。你只要简单地循环遍历DataTables中的竖栏,并将栏名称与商业对象中的属性名称动态匹 配。
还可用反射将一个对象的属性与一个存储程序参数动态捆绑起来。这个捆绑过程允许你建立普通的数据访问方法,提供代码生成工具为你带来的许多完全动态的优势。因此,反射能够显著减少代码长度,并缓解应用维护压力。
简单介绍
在本文中,我们只是触及问题的表层,说明反射能够帮助开发者编写更好的代码。在以后的文章中,我将以这篇介绍性的文章为基础,更加详细的说明反射的其他应 用与功能。我要讨论的主题包括访问方法和在运行时的类属性、从数据结构中提取商业对象、以及建立一个可由多个项目应用的普通数据访问层。
[原创]面向生命(Life oriented 简称 LO)编程
序言:
软件是个生命体!
万事万物皆变化!
为什么我会提出”面向生命(Life oriented)”编程的思想,因为我们一直以来以建筑学的角度来审视软件工程,将软件定义为一种无生命的产品,而事实是外界的需求的无时无刻都在变化要求我们做出来的软件也随之变化,你难道想让一所盖好的房子会每时每刻根据外界的环境变化吗?而有生命的植物和动物则可以,会依据环境的变化而变化,一株草会根据压在上方的石头而改变自身的生长形态而曲折生长,软件应该也会为适应变化而调整自身的结构和功能来避免被变化的环境所淘汰!没错这是个适者生存的世界,软件也一样。
还有一个原因就是软件和人一样是有生、老、病、死的,诞生的时候具有面向对象思想中人类的基本属性和行为,但是还很弱,就像婴儿一样,但是面向对象的思想将世界万物都抽象成类,类的实例创建了对象,但是根本没有发现一类的对象之间是存在差异的,难道你看到过世界上长的完全一模一样的人吗?没有,因为每个人都是鲜活的生命体,尽管具有人类的共同属性和行为,但是每个人都有自己的性格、学习能力、、、、、、、,同时每个人的成长历程是根据环境的不同而不同,也就是适应变化,刚生下来的婴儿是最原始的对象,然后通过人类具有的基本行为嗅觉、听觉、视觉、味觉、触觉、学习能力来获得信息不断完善对世界的认识,从而形成不同的性格,也逐渐成长起来从需要外界服务,到能够对外界提供服务,而每个人接受的知识和自己的能力决定了最终他能够为外界提供哪种服务,随着时间周期和自身的消耗慢慢老化,直至死亡,软件也是如此,开始我们只是依据目前的静止的需求将其创建出来,可我们错就错在用一种静止的眼光去看待软件,其实它是在我们的不断提供信息的过程中,不断成长,同时从我们提供的信息中它在学习强化了自身的功能,并能够提供给我们更多功能,也就是目前各大网站提供的对外接口服务,其实yahoo或google开始这些网站系统是没有能力提供这些服务的,为什么是因为它们没有足够支持这些服务的信息,就好比它们开始只是婴儿还需要我们提供信息给它,让它成长一样,当它在我们不断的信息营养下成长成为一个巨人的时候,它们反过来能够为我们做更多以往我们都没有想过能做的事,这就是一个软件生命体,而不是我们传统意义上的建筑,建筑的功能是有限的而生命体的功能是无限的,因此你硬要将一个不变的软件去适应不断变化的环境那是种错误!因此,我们需要一种全新的思想去指导我们去设计软件那就是“面向生命”!
第一章:什么是面向生命编程
面向生命编程是以面向对象为基础,将对象赋予生命特质的一种编程思想。
面向生命编程将世界中具有相同属性和行为的事物化为为”类“,”类“的具体实例称为”对象“,每个对象都具有“繁殖”能力,繁殖的定义是同类的一个或多个对象通过“结合”产生”亲子对象“,”亲子对象“具有父类的”遗传“属性和行为,同时具有特有的”个性“的属性和行为,“生命体”是独立的个体,它具有“学习”、“分析”、“判断”、“成长”、“创造”能力,它通过对外界提供给它的信息内容利用“判断”和“分析”后,经过“学习”然后“创造”出”自制“的功能,以”服务“的方式提供给外界进行使用。”生命体”具有“模仿”能力,它通过外界提供的对某种功能的“描述”然后对描述进行“分析”、“判断”然后结合自身的“信息”资源进行“创造”出具有同等功能的能力从而达到“模仿”。
生命与应用系统的对应关系图:
生命体:就是最终的应用软件系统
骨骼:等同于应用系统的目录结构,用于支撑整个系统运行的整体的存储结构。
神经系统:就是大脑,是整个软件系统的核心,用于支配和调度各个”服务单元“运行实现”能力“的中枢,本身具有”记忆“、”学习“、”分析“的能力。
器官:对应软件系统中的服务单元,只具有某种能力的独立单元,通过对外界提供服务来实现某种能力,同时也具有自己的学习、分析、能力,对采集到的外界信息进行汇总分析并进行学习,来完成新能力的实现过程。
血液:对应软件系统中流淌的信息元,也就是独立的信息实体对象,每个信息对象也是独立的生命体,就像社会中的人一样,它具有独立的能力,承载独立的个性,穿行与整个系统中,并在神经系统的控制下在各个器官间穿行,为器官提供信息,同时获得器官处理后的信息。是整个系统的动力源泉,没有血液的系统是个死生命体,有了血液才能让生命体不断的成长。
皮肤:对外的表现形势,可以是页面、xml、、、等等用户易于操作的形势,甚至是视频或是图片、声音、信号等媒体
[教程]说说大型高并发高负载网站的系统架构
http://blog.csdn.net/starxu85/archive/2008/02/24/2116593.aspx
一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站 对系统架构、性能的要求都很简单,随着互联网业务的不断丰富,网站相关的技术经过这些年的发展,已经细分到很细的方方面面,尤其对于大型网站来说,所采用 的技术更是涉及面非常广,从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有了很高的要求,已经不是原来简单的html静态网站 所能比拟的。
大型网站,比如门户网站。在面对大量用户访问、高并发请求方面,基本的解决方案集中在这样几个环节:使用高性能的服务器、高性能的数据库、高效率的编程语言、还有高性能的Web容器。但是除了这几个方面,还没法根本解决大型网站面临的高负载和高并发问题。
上面提供的几个解决思路在一定程度上也意味着更大的投入,并且这样的解决思路具备瓶颈,没有很好的扩展性,下面我从低成本、高性能和高扩张性的角度来说说我的一些经验。
1、HTML静态化
其 实大家都知道,效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有 效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点的新 闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限管 理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。
除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子、文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop的大杂烩就是使用了这样的策略,网易社区等也是如此。
同 时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来实现,比如论坛中论 坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这部分 内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求。
2、图片服务器分离
大家知道,对于Web服务器来说,不管 是Apache、IIS还是其他容器,图片是最消耗资源的,于是我们有必要将图片与页面进行分离,这是基本上大型网站都会采用的策略,他们都有独立的图片 服务器,甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力,并且可以保证系统不会因为图片问题而崩溃,在应用服务器和图片服务 器上,可以进行不同的配置优化,比如apache在配置ContentType的时候可以尽量少支持,尽可能少的LoadModule,保证更高的系统消 耗和执行效率。
3、数据库集群和库表散列
大型网站都有复杂的应用,这些应用必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就能显现出来,这时一台数据库将很快无法满足应用,于是我们需要使用数据库集群或者库表散列。
在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是类似的方案,您使用了什么样的DB,就参考相应的解决方案来实施即可。
上 面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库表散列是常用并且最 有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者功能 进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就是采用了这样的架 构,将论坛的用户、设置、帖子等信息进行数据库分离,然后对帖子、用户按照板块和ID进行散列数据库和表,最终可以在配置文件中进行简单的配置便能让系统 随时增加一台低成本的数据库进来补充系统性能。
4、缓存
缓存一词搞技术的都接触过,很多地方用到缓存。网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存。高级和分布式的缓存在后面讲述。
架构方面的缓存,对Apache比较熟悉的人都能知道Apache提供了自己的缓存模块,也可以使用外加的Squid模块进行缓存,这两种方式均可以有效的提高Apache的访问响应能力。
网 站程序开发方面的缓存,Linux上提供的Memory Cache是常用的缓存接口,可以在web开发中使用,比如用Java开发的时候就可以调用MemoryCache对一些数据进行缓存和通讯共享,一些大 型社区使用了这样的架构。另外,在使用web语言开发的时候,各种语言基本都有自己的缓存模块和方法,PHP有Pear的Cache模块,Java就更多 了,.net不是很熟悉,相信也肯定有。
5、镜像
镜像是大型网站常采用的提高性能和数据安全性的方式,镜像的技术可以解决不同网 络接入商和地域带来的用户访问速度差异,比如ChinaNet和EduNet之间的差异就促使了很多网站在教育网内搭建镜像站点,数据进行定时更新或者实 时更新。在镜像的细节技术方面,这里不阐述太深,有很多专业的现成的解决架构和产品可选。也有廉价的通过软件实现的思路,比如Linux上的rsync等 工具。
6、负载均衡
负载均衡将是大型网站解决高负荷访问和大量并发请求采用的终极解决办法。
负载均衡技术发展了多年,有很多专业的服务提供商和产品可以选择,我个人接触过一些解决方法,其中有两个架构可以给大家做参考。
硬件四层交换
第 四层交换使用第三层和第四层信息包的报头信息,根据应用区间识别业务流,将整个区间段的业务流分配到合适的应用服务器进行处理。 第四层交换功能就象是虚 IP,指向物理服务器。它传输的业务服从的协议多种多样,有HTTP、FTP、NFS、Telnet或其他协议。这些业务在物理服务器基础上,需要复杂的 载量平衡算法。在IP世界,业务类型由终端TCP或UDP端口地址来决定,在第四层交换中的应用区间则由源端和终端IP地址、TCP和UDP端口共同决 定。
在硬件四层交换产品领域,有一些知名的产品可以选择,比如Alteon、F5等,这些产品很昂贵,但是物有所值,能够提供非常优秀的性能和很灵活的管理能力。Yahoo中国当初接近2000台服务器使用了三四台Alteon就搞定了。
软件四层交换
大家知道了硬件四层交换机的原理后,基于OSI模型来实现的软件四层交换也就应运而生,这样的解决方案实现的原理一致,不过性能稍差。但是满足一定量的压力还是游刃有余的,有人说软件实现方式其实更灵活,处理能力完全看你配置的熟悉能力。
软 件四层交换我们可以使用Linux上常用的LVS来解决,LVS就是Linux Virtual Server,他提供了基于心跳线heartbeat的实时灾难应对解决方案,提高系统的鲁棒性,同时可供了灵活的虚拟VIP配置和管理功能,可以同时满 足多种应用需求,这对于分布式的系统来说必不可少。
一个典型的使用负载均衡的策略就是,在软件或者硬件四层交换的基础上搭建squid集群,这种思路在很多大型网站包括搜索引擎上被采用,这样的架构低成本、高性能还有很强的扩张性,随时往架构里面增减节点都非常容易。这样的架构我准备空了专门详细整理一下和大家探讨。
对于大型网站来说,前面提到的每个方法可能都会被同时使用到,我这里介绍得比较浅显,具体实现过程中很多细节还需要大家慢慢熟悉和体会,有时一个很小的squid参数或者apache参数设置,对于系统性能的影响就会很大,希望大家一起讨论,达到抛砖引玉之效。
[教程]什么是CMS(内容管理系统)
CMS是Content Management System的缩写,意为”内容管理系统”。
CMS具有许多基于模板的优秀设计,可以加快网站开发的速度和减少开发的成本。
CMS的功能并不只限于文本处理,它也可以处理图片、Flash动画、声像流、图像甚至电子邮件档案。
CMS还分各个平台脚本种类的。
内容管理系统是企业信息化建设和电子政务的新宠,也是一个相对较新的市场,对于内容管理,业界还没有一个统一的定义,不同的机构有不同的理解:
Gartner Group 认为内容管理从内涵上应该包括企业内部内容管理、Web内容管理、电子商务交易内容管理和企业外部网(Extranet)信息共享内容管理(如CRM和 SCM等),Web内容管理是当前的重点,e-business和XML是推动内容管理发展的源动力。
Merrill Lynch的分析师认为内容管理侧重于企业员工、企业用户、合作伙伴和供应商方便获得非结构化信息的处理过程。内容管理的目的是把非结构化信息出版到 intranets, extranets和ITE(Internet Trading Exchanges), 从而使用户可以检索、使用、分析和共享。商业智能系统 (BI)侧重于结构化数据的价值提取,而内容管理则侧重于企业内部和外部非结构化资源的战略价值提取。
Giga Group 认为作为电子商务引擎,内容管理解决方案必须和电子商务服务器紧密集成,从而形成内容生产(Production)、传递(Delivery)以及电子商务端到端系统。
我们认为内容管理系统是一种位于WEB前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容管理解决方案重点解决各种非结构化或半结构化的数字资源的采集、管理、利用、传递和增值,并能有机集成到结构化数据的商业智能环境中,如OA,CRM等。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。这里指的”内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到 Internet、Intranet以及Extranet网站的信息。
CMS是如何应运而生的?
随着网络应用的丰富和发展,很多网站往往不能迅速跟进大量信息衍生及业务模式变革的脚步,常常需要花费许多时间、人力和物力来处理信息更新和维护工作;遇到网站扩充的时候,整合内外网及分支网站的工作就变得更加复杂,甚至还需重新建设网站;如此下去,用户始终在一个高成本、低效率的循环中升级、整合……
于是,我们听到许多用户这样的反馈:
页面制作无序,网站风格不统一,大量信息堆积,发布显得异常沉重;
内容繁杂,手工管理效率低下,手工链接视音频信息经常无法实现;
应用难度较高,许多工作需要技术人员配合才能完成,角色分工不明确;
改版工作量大,系统扩展能力差,集成其它应用时更是降低了灵活性;
对于网站建设和信息发布人员来说,他们最关注的系统的易用性和的功能的完善性,因此,这对网站建设和信息发布工具提出了一个很高的要求。
首先,角色定位明确,以充分保证工作人员的工作效率;其次,功能完整,满足各门道”把关人”应用所需,使信息发布准确无误。比如,为编辑、美工、主编及运维人员设置权限和实时管理功能。
此外,保障网站架构的安全性也是用户关注的焦点。能有效管理网站访问者的登陆权限,使内网数据库不受攻击,从而时刻保证网站的安全稳定,免于用户的后顾之忧。
根据以上需求,一套专业的内容管理系统CMS应运而生,来有效解决用户网站建设与信息发布中常见的问题和需求。对网站内容管理是该软件的最大优势,它流程完善、功能丰富,可把稿件分门别类并授权给合法用户编辑管理,而不需要用户去理会那些难懂的SQL语法。
CMS是如何发展的?
内容管理从2000年开始成为一个重要的应用领域,这时.COM和B2B, B2C等经历了资本和市场的考验及洗礼,人们重新回到信息技术应用的基本面-如何提高竞争能力,而内容管理恰恰能够通过对企业各种类型的数字资产的产生、管理、增值和再利用,改善组织的运行效率和企业的竞争能力,企事业单位也开始认识到内容管理的重要性。
从企事业单位信息化的观点来看,以下因素导致对内容管理软件的巨大需求:
(1) 知识是企业的财富。在Internet交互过程中,只有十分之一涉及销售,其他十分之九都和信息交互有关,员工的知识获取越来越依赖于互联网,特别是在电子商务的个性化环境中,客户为了做出购买决定,需要智能化地获取信息,不仅仅是商品的数量和价格,更重要的可能是产品的手册、安全保证、技术指标、售后服务、图片文件等等。
(2) 信息的及时性和准确性。无论在企业内网还是外网,信息的更新越来越快,企事业单位的信息生产量越来越多,且呈现成倍增长的趋势,企事业单位更需要的是一个功能强大、可扩展的、灵活的内容管理技术来满足不断的信息更新、维护,这时如何保证信息的准确性和真实性将越来越显得重要。
(3) 企业内外网统一的需求增长。随着企事业单位信息化的建设,内联网和外联网之间的信息交互越来越多,优秀的内容管理系统对企业内部来说,能够很好地做到信息的收集和重复利用以及信息的增值利用, 对于外联网来说,更重要的是真正交互式和协作性的内容。
国外从事内容管理软件研发的主要厂商包括Vignette,Interwoven, BroadVision, Openmarket,ATG, Allaire, Documentum, Hummingbird等,这些公司CM产品和解决方案专业性很强,大多基于J2EE等平台,功能丰富,主要面向企业级用户,是CM市场的主要厂商。还有一些更窄的专业厂商提供内容管理某个阶段需要的功能,如Verity 提供知识检索,Micromedia 提供内容创作平台,Akamai和Inkitomi 提供内容分发管理技术等。与此相反,Microsoft, IBM, oracle等公司提供通用平台性CM解决方案。但是目前CM市场仍有很多不完善的地方,包括:
在这个全新的市场中很难找到一个CMS满足用户的所有需求。
有些CMS只是单纯的信息发布工具而以,称不上内容的收集和再利用更谈不上知识管理的概念,最多只是一组网站建设工具软件而已。
所有产品的可视链接都非常差,只有极少数厂商能够提供可视软件,这些软件都不是交互式的,不能用作管理工具。
CMS都有可能包括些什么?
隐藏在内容管理系统(CMS)之后的基本思想是分离内容的管理和设计。页面设计存储在模板里,而内容存储在数据库或独立的文件中。当一个用户请求页面时,各部分联合生成一个标准的 HTML 页面。
一个内容管理系统通常有如下要素:
文档模板
脚本语言或标记语言
与数据库集成
内容的包含物由内嵌入页面的特殊标记控制。这些标记对于一个内容管理系统通常是唯一的。这些系统通常有对较复杂的操作的语言支持,如 Python, Perl, 或 Java 等。
内容管理系统对站点管理和创造编辑都有好处。这其中最大的好处是能够使用模板和通用的设计元素以确保整个网站的协调。作者只需在他们的文档中采用少量的模板代码,然后即可把精力集中在设计之上的内容了。要改变网站的外观,管理员只需修改模板而不是一个个单独的页面。
内容管理系统也简化了网站的内容供给和内容管理的责任委托。很多内容管理系统允许对网站的不同层面人员赋予不同等级的访问权限,这使得他们不必研究操作系统级的权限设置,只需用浏览器接口即可完成。
其他的特性如:搜索引擎、日历、Web 邮件等也会内置于内容管理系统 CMS 内,或允许以第三方插件的形式集成进来。
如何开发CMS
内容管理系统是一个很泛的概念:从商业门户网站的新闻系统到个人的Weblog都可以称作发布系统。
框架型:本身不包含任何应用实现,只是提供了底层框架,具体应用需要一定的二次开发,比如Cocoon,Vignette;
应用型:本身是一个面向具体类型的应用实现,已经包含了新闻/评论管理,投票,论坛,WIKI等一些子系统。比如:postNuke xoops等;
但无论如何,在发布系统选型之前,首先了解自己的实际需求是最重要的:想根据现成系统将自己的需求硬往上照搬是非常不可取的。访问量,权限控制和各种功能需求。每个模块和功能自己都比较清晰一点以后,再去网上找找类似的实现:你会发现其实每个环节到目前上都有比较成熟的实现了,而且还在不断完善和发展中,如果没有:你的需求太特殊,或者可以尝试分解成更小的系统组合实现。
内容管理系统被分离成以下几个层面:各个层面优先考虑的需求不同
1,后台业务子系统管理(管理优先:内容管理):新闻录入系统,BBS论坛子系统,全文检索子系统等,针对不同系统的方便管理者的内容录入:所见即所得的编辑管理界面等,清晰的业务逻辑:各种子系统的权限控制机制等;
2,Portal系统(表现优先:模板管理):大部分最终的输出页面:网站首页,子频道/专题页,新闻详情页一般就是各种后台子系统模块的各种组合,这种发布组合逻辑是非常丰富的,Portal系统就是负责以上这些后台子系统的组合表现管理;
3,前台发布(效率优先:发布管理):面向最终用户的缓存发布,和搜索引擎spider的URL设计等……
内容管理和表现的分离:很多成套的CMS系统没有把后台各种子系统和Portal分离开设计,以至于在Portal层的模板表现管理和新闻子系统的内容管理逻辑混合在一起,甚至和BBS等子系统的管理都耦合的非常高,整个系统会显得非常庞杂。而且这样的系统各个子系统捆绑的比较死,如果后台的模块很难改变。但是如果把后台各种子系统内容管理逻辑和前台的表现/发布分离后,Portal和后台各个子系统之间只是数据传递的关系:Portal只决定后台各个子系统数据的取舍和表现,而后台的各个子系统也都非常容易插拔。
内容管理和数据分发的分离:需要要Portal系统设计的时候注意可缓存性(Cache Friendly)性设计:CMS后台管理和发布机制,本身不要过多考虑”效率”问题,只要最终页面输出设计的比较Cacheable,效率问题可通过更前端专门的缓存服务器解决。
此外,就是除了面向最终浏览器用户外,还要注意面向搜索引擎友好(Search engine Friendly)的URL设计:通过 URL REWRITE转向或基于PATH_INFO的参数解析使得动态网页在链接(URI)形式上更像静态的目录结构,方便网站内容被搜索引擎收录;
都有哪些CMS提供商
Vignette. 奥斯汀, TX Vignette公司,网站内容管理系统的领导者,今天宣布在中层楼资金上它取得了1亿4千万美元,成为奥斯汀基础软件公司中最大的私人资产投资,同时也使Vignette成为在奥斯汀发展最快的互联网软件公司。 Vignette 公司,作为全世界网站内容应用系统的领导者,为公司们提出了解决方案——在互联网上建立非常成功的商业。 Vignette的王牌产品是StoryServer 3,它能使公司以应用软件(如在线发布、知识管理和复杂电子商务系统)为基础建立、管理和发布服务,最终加速和提高客户的忠实度和持续力。超过75个一流公司,包括Ziff- Davis' ZDNet, First Chicago NBD, Bay Networks 和 CNET ,使用StoryServer 3 ,每天提供2500万个网页浏览。 StoryServer3 获得了5个行业奖励,包括UPSIDE杂志的”网络基础组织类最活跃的私人公司” 。 它的 V/5 系列是一套应用软件包,设计用来为门户、B2C 和 B2B 市场需求提供内容管理。 V/5系列具有高度的可定制化能力和广泛的功能,它包括内容和模板的开发、个性化定制和发布。但是,它的多数功能还需要开发。
Documentum. Documentum 是文档管理解决方案的长期供应商。带着它的4i 网站内容管理(WCM)版本,公司有力地进入了CM舞台,它提供了一个解决方案来支持具有在线而动态的内容的电子商务应用软件。对大中型组织来说,它也是一个健全的可扩展的网站内容管理解决方案。
Eprise. Eprise的 Participant Server 2.6.6是该公司内容管理的产品,它为大型商务和.com提供商业应用软件,包括互联网、企业内部网和公共网站。该产品能促进内容添加、修改和全球发布。 Participant Server 的主要组件包括内容中心、操作中心、共享中心和内容分配套件。产品为投稿和创造提供基于网络的界面,同时内容分配组件处理适于交易的内容分配。 A single Web based administrative interface is a plus because administration can be distributed across the organization. 单一的基于网络的管理界面是附加的,因为管理在组织范围内可以是分布式的。
Interwoven. Interwoven的 TeamSite 4.5是横向聚焦的网站内容管理解决方案,它向财富500强和全球2000个上市公司提供企业范围的网站内容管理。TeamSite 的管理和组成能力通过桌面和基于Java的接口提供,这种桌面和接口作为操作系统的一部分出现。用户可以通过Windows Explorer把内容拖放到存储库中。
Xpedio. Xpedio CMS 4.0是全球 2000 B2B 和 B2E 公司所用的解决方案包,它为没有技术的用户提供了容易使用的网站建设能力。该产品在企业内部互联网、外部互联网和电子商务网站上促进了内容的快速发展和管理。在管理和发布内容方面,它是强大的解决方案,它提供具有分布式管理能力的创作工具、安全、发布的灵活性和完全基于浏览器的界面。
Ncompass. NCompass Labs于2001年4月通过微软成立,现在它是微软的子公司。 Resolution 3.1是Ncompass的浏览器,以网站内容管理解决方案为基础,在2001年底,它做为微软的产品(称为微软内容管理服务器)再次发布。
Open Market. Open Market 的Content Server 3.1是 J2EE兼容的内容管理解决方案,它嫦虺霭妗⒚教搴徒鹑诜务市常Open Market 把内容服务器定位为推动以内容为中心的电子商务应用软件的产品,它处理访问者、客户和合作者之间的交互。该产品有用于管理和组织的网络界面,包括了一个个性化的引擎和用于发布的应用软件服务器。
BroadVision. BroadVision 把应用方法用于内容管理,主要目标是B2B, B2E 和 B2C 市场。 BroadVision以应用软件程序包的形式出售产品,如出售给附带商业、合作商业、市场和雇员自我服务。内容管理解决方案也独立地出售。
FileNET. FileNET 是文档管理市场的传统领导者,现在它集中精力于生产电子商务应用软件的Panagon生产线。它的网站内容管理套件包括Panagon 内容服务(PCS)、Panagon 网络发布者(PWP)、Panagon 网络服务(PWS)和Panagon 电子流程。FileNET套件主要面向于金融、保险、政府、电信、公共事业和制造业。FileNET把它的网站内容管理套件定位在内容管理的全部解决方案,它贯穿内容的生命周期,从创造到审批、发布和分配。然而,在它目前的版本中,产品在核心网站内容管理的功能性上需要重大发展,如个性化和动态内容的表达。
Megellan. 2000 年7月,Gauss Interprise 和美国软件开发者Magellan 合并,主要销售它的内容管理系列 Versatile Internet Platform (VIP)。VIP定位于企业管理内容、网站内容和门户的平台。对于集中的环境,产品系列有适应需求的基本功能,包括基于网络的管理,单一和大批的输入、第三方厂商提供的基本库服务、以及用于分布式内容创造的模板设计工具。
InStranet. InStranet 成立于1999年,总部设在纽约,并且在巴黎设有欧洲总部。公司的王牌产品是InStranet 2000 1.5,它是一个浏览器和基于Java的网站内容管理解决方案。产品聚焦于,在B2B和雇员工作环境下,向企业内部互联网和外部互联网发布业务文件和内容。InStranet 2000 1.5在 J2EE兼容的应用服务器上运行,已在BEA WebLogic, IBM WebSphere 和 iPlanet 应用服务器上经过检验。
Mediasurface. Mediasurface 的总部设在伦敦,它的美国办事处在纽约和弗朗西丝科。公司为组织提供管理内容软件,用于企业内部互联网和外部互联网。公司的核心产品是 Mediasurface 3.5,它瞄准垂直市场,包括金融服务、政府、教育、卫生保健、IT服务、媒体、出版和广播、零售和消费服务。
Six Open Systems. Six Offene Systeme GmbH 在美国称为Six Open Systems (Six) ,于1991年在德国成立。Six在德国有重要的消费群,它以产品Six CMS 4.0打入美国市场。该产品是由内到外的、以浏览器为基础的解决方案,它用来帮助媒体出版商简化和管理内容设计及网页和门户、互联网、企业内部互联网等的设计。
Starbase. Starbase 销售合作产品,该产品为电子商务应用软件创造、管理代码和内容。2001年2月, Starbase收购了worldweb.net 和它的产品 Expressroom I/O 、以及基于Java 和 XML的网站内容管理解决方案。Starbase正把Expressroom I/O添加到它的代码和内容管理解决方案的协作套件中。
国内用的比较多的有Active Context、turbocms、cms4i,不过这些都是纯商业性系统,价格很高,一般个人建站,建议选取一些国外比较有名的开源系统,如 Mambo、Drupal、Tikiwiki、PhpNuke、 PostNuke、Xoops、Tikipro、不过这些全是基于php + mySQL的,众所周知,php和mysql是免费的嘛^__^
[资源]CMS内容管理系统的设计和选型
内容管理系统(CMS)的设计和选型
内容管理系统概述
内容管理系统是一个很泛的概念:从商业门户网站的新闻系统到个人的Weblog都可以称作发布系统。
- 框架型:本身不包含任何应用实现,只是提供了底层框架,具体应用需要一定的二次开发,比如Cocoon,Vignette;
- 应用型:本身是一个面向具体类型的应用实现,已经包含了新闻/评论管理,投票,论坛,WIKI等一些子系统。比如:postNuke xoops等;
但 无论如何,在发布系统选型之前,首先了解自己的实际需求是最重要的:想根据现成系统将自己的需求硬往上照搬是非常不可取的。访问量,权限控制和各种功能需 求。每个模块和功能自己都比较清晰一点以后,再去网上找找类似的实现:你会发现其实每个环节到目前上都有比较成熟的实现了,而且还在不断完善和发展中,如 果没有:你的需求太特殊,或者可以尝试分解成更小的系统组合实现。
内容管理系统被分离成以下几个层面:各个层面优先考虑的需求不同
- 后台业务子系统管理(管理优先:内容管理):新闻录入系统,BBS论坛子系统,全文检索子系统等,针对不同系统的方便管理者的内容录入:所见即所得的编辑管理界面等,清晰的业务逻辑:各种子系统的权限控制机制等;
- Portal系统(表现优先:模板管理):大部分最终的输出页面:网站首页,子频道/专题页,新闻详情页一般就是各种后台子系统模块的各种组合,这种发布组合逻辑是非常丰富的,Portal系统就是负责以上这些后台子系统的组合表现管理;
- 前台发布(效率优先:发布管理):面向最终用户的缓存发布,和搜索引擎spider的URL设计等……
内 容管理和表现的分离:很多成套的CMS系统没有把后台各种子系统和Portal分离开设计,以至于在Portal层的模板表现管理和新闻子系统的内容管理 逻辑混合在一起,甚至和BBS等子系统的管理都耦合的非常高,整个系统会显得非常庞杂。而且这样的系统各个子系统捆绑的比较死,如果后台的模块很难改变。 但是如果把后台各种子系统内容管理逻辑和前台的表现/发布分离后,Portal和后台各个子系统之间只是数据传递的关系:Portal只决定后台各个子系 统数据的取舍和表现,而后台的各个子系统也都非常容易插拔。
内容管理和数据分发的分离:需要要Portal系统设计的时候注意可缓存性(CacheFriendly)性设计:CMS后台管理和发布机制,本身不要过多考虑“效率”问题,只要最终页面输出设计的比较Cacheable,效率问题可通过更前端专门的缓存服务器解决。
此外,就是除了面向最终浏览器用户外,还要注意面向搜索引擎友好(Searchengine Friendly)的URL设计:通过URLREWRITE转向或基于PATH_INFO的参数解析使得动态网页在链接(URI)形式上更像静态的目录结构,方便网站内容被搜索引擎收录;
--------------- --------------- --------------- |新闻管理子系统| | BBS论坛子系统| | 商城子系统 | --------------- --------------- --------------- | \ / | \ / 内 | ----------|--- \ / 容 <== 业务子系统(零件生产) | / | \ \ / 管 --------------- | --------------- 理 |专题制作子系统| | |全文检索子系统| --------------- | --------------- \ | / -------------------------|--------------------------------------------- \ | / 频 --------------- 道 <== Portal系统(产品组装) | Portal 系统 | 管 --------------- 理 | -------------------------|--------------------------------------------- | 前 | 台 <== 发布系统(分发代理) --------------- 发 |前台发布系统 | 布 --------------- / \ / \ --------------- --------------- | 用户浏览器 | |Search Engine| --------------- ---------------
这里,我把在内容发布系统选型中找到的一些资料总结如下:
内容管理系统的选型
关键词:CMS Content Manage System
CMS行业研究
http://www.cmswatch.com
http://www.cmsreview.com
http://www.cmsinfo.org
CMS讨论邮件列表
http://www.cms-list.org
商业软件和开源项目列表:
http://directory.google.com/Top/Computers/Software/Internet/Site_Management/Content_Management/
推荐:基于XML的发布框架
http://cocoon.apache.org/
具体实现复杂程度可能会根据需求的不同而不同,但越是大型的系统越是需要分工:将内容(数据),表现(模板)和应用逻辑(程序)尽可能分离和对这3者的管理。
Portal—门户系统
Open source Projects:
http://jportlet.sourceforge.net/
Apache Software Foundation: Jakarta JetSpeed 1.3
JetSpeed home page: http://jakarta.apache.org/jetspeed/site/index.html
JetSpeed Portlet API: http://cvs.apache.org/viewcvs/jakarta-jetspeed/proposals/portletAPI/
http://www.liferay.com/home/index.jsp
http://basicPortal.com/
http://www.jahia.org/
http://jporta.sourceforge.net/
商业软件:
BEA WebLogic Portal – http://edocs.bea.com/wlp/docs81/javadoc/com/bea/Portal/model/Portlet.html
IBM Websphere Portal – http://www.software.ibm.com/wsdd/zones/Portal/
Oracle Portal Developer Kit – http://Portalstudio.oracle.com/
其它:
PSML – http://jakarta.apache.org/jetspeed/site/psml.html
BEA: Web Logic Portal 4.0 http://www.bea.com/products/weblogic/Portal/index.shtml
IBM: WebSphere Portal 2.1 http://www-4.ibm.com/software/webservers/Portal/
iPlanet: iPlanet Portal Server 3.0 http://www.iplanet.com/products/iplanet_Portal/home_Portal.html
Oracle: oracle 9i Portal http://www.oracle.com/ip/deploy/ias/Portal/index.html
SAP Portal: http://www.iviewstudio.com
Epicentric Portal: http://www.epicentric.com/solutions/products/efs/
参考:
Wafer:Java开发框架研究
http://www.waferproject.org/index.html
门户(Portal)系统相关开发框架:
http://udoo.51.net/mt/archives/000011.html
广告管理系统
关键词:ad server
广告系统和内容的分离,可以大大降低系统之间的关联度。
专业行业研究网站:
http://adres.internet.com
相关厂商和开源项目:
http://directory.google.com/Top/Computers/Programming/Languages/PHP/Scripts/Ad_Management/?il=1
http://directory.google.com/Top/Computers/Software/Internet/Servers/Advertising/?tc=1
http://www.jspin.com/home/apps/admanage?cob=winedit
http://www.scriptdex.com/dex/php_ad_management.shtml
推荐:
http://www.phpadsnew.com/功能性比较强
http://oasis.sourceforge.net/免费 基于日志记录和定期导入MYSQL统计,可以负载50万请求/每小时 以上
如果看重广告的第3方特性,可以选择第三方服务:
http://www.doubleclick.net/
http://www.allyes.com/
论坛/社区系统
关键词: BBS FORUM
论坛软件介绍:
http://directory.google.com/Top/Computers/Internet/Web_Design_and_Development/Message_Boards/
推荐:
http://www.phpBB.com PHP + MySQLopen source
http://www.vbulletin.com/order/PHP + MySQL 有付费的商业支持85-160$
http://www.jivesoftware.com/products/pricing.jsp商业论坛系统,1000$-2500$ 有知识库扩展应用
http://yazd.yasna.com/features.jsp基于 Java
所见即所得(WYSIWYG)编辑器
在内容的录入管理方面,所见即所得是比较重要的,这样可以大大简化对系统中布局排版的需求。
基于浏览器的WYSIWYG(所见即所得)编辑器是CMS设计中,编辑工具的主要考虑方面。目前主要是通过JavaScript调用IE或其他浏览器的内置方法实现。其中基于IE5.5浏览器的实现最为简洁。这里有一个完整的例子:
Building a WYSIWYG HTML Editor Part 1/2
Building a WYSIWYG HTML Editor Part 2/2
主要功能:
- 能够通过JavaScript实现的基本功能:加粗,斜体字,居中,添加链接,添加图片,模式切换:HTML和文本模式的切换,
- Word垃圾代码过滤
- 图片上载接口:图片上载最好通过其他独立模块实现。
选型指标:
- 不依赖服务器端代码:只通过JAVASCRIPT或客户端控件实现代码,可以保证以后系统迁移的方便。
- WORD垃圾代码过滤
可视化编辑器大全:
http://www.bris.ac.uk/is/projects/cms/ttw/ttw.html
推荐:
http://www.aine.be/aynhtml/
图片/文件上传组建
图片和文件等非结构化数据还是分别使用另外的服务解决比较好。这样可以大大简化CMS本身的复杂程度。
推荐:
文件上传:
Apache Commons项目
http://jakarta.apache.org/commons/
ImageJ:图片处理缩略图生成和水印等
http://rsb.info.nih.gov/ij/
关于Blog系统的选型,目前主流的基于PHP的包括:
· Nucleus 3.0 www.nucleuscms.org
· pmachine 2.3 www.pmachine.com
· b2evolution 0.9.0.3 www.b2evolution.net
· Serendipity 0.6 www.s9y.org
· WordPress 1.2 www.wordpress.org
· bBlog 0.7.3 www.bblog.com
· pLog 0.3.1 www.plogworld.org
· Simplog .9 www.simplog.org
· Textpattern 1.18a www.textpattern.com
Mikel



