二十四画生的Blog


        ——开始学习Orchard框架
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
在Orchard中有一个非常好用的命令行工具(Command-Line),我们可通过运行一些命令执行多种操作,如:创建代码模板,打包模块,启用功能等等。关于命令行工具的更多介绍,可以查看《Orchard中的命令行工具》。如何才能定义我们自己特有的命令,下面我们还是用以前所开发的产品示例模块来举例说明。
 

首先,我们按照Orchard中的一些约定和规范在MyCompany.Products项目中添加一个Commands目录,并在此目录中添加一个ProductCommands.cs文件。例如,我们希望能够在命令行工具中添加我们要用到产品分类,并能通过相应命令快速创建产品,我们就可以通过输入以下代码实现。

 

 

ProductCommands.cs
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using Orchard.Commands;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.Core.Common.Models;
using Orchard.Core.Navigation.Models;
using Orchard.Core.Routable.Models;
using Orchard.Core.Routable.Services;
using Orchard.Security;
using MyCompany.Products.Services;
using Orchard.Core.Navigation.Services;
using Orchard.Settings;
using Orchard.Data;
using MyCompany.Products.Models;
using Orchard;

namespace MyCompany.Products.Commands
{
    
/// <summary>
    
/// 定义命令行功能,默认需要继承DefaultOrchardCommandHandler类
    
/// </summary>
    public class ProductCommands : DefaultOrchardCommandHandler 
    {
        
private readonly IContentManager _contentManager;
        
private readonly IRepository<CategoryPartRecord> _categoryRepository;

        
public ProductCommands(IContentManager contentManager, IRepository<CategoryPartRecord> categoryRepository)
        {
            _contentManager 
= contentManager;
            _categoryRepository 
= categoryRepository;
        }

        
/// <summary>
        
/// 加上OrchardSwitch属性表示改字段可以通过命令行参数来获取值
        
/// </summary>
        [OrchardSwitch]
        
public string Slug { getset; }

        [OrchardSwitch]
        
public string Title { getset; }

        [OrchardSwitch]
        
public string Price { getset; }

        [OrchardSwitch]
        
public string Brand { getset; }

        [OrchardSwitch]
        
public string CategoryName { getset; }

        [OrchardSwitch]
        
public string Description { getset; }



        
/// <summary>
        
/// 在方法上加上
        
/// CommandName,定义命令名
        
/// CommandHelp,定义命令帮助
        
/// </summary>
        
/// <param name="categoryName">以空格为分隔依次接收此命名后的多个参数,当需要传递有空格的值可以加上引号</param>
        
/// <returns></returns>
        [CommandName("product category create")]
        [CommandHelp(
"product category create <category-name>\r\n\t" + "Creates a new product category")]
        
public string CreateCategory(string categoryName) 
        {
            
if (String.IsNullOrEmpty(categoryName))
            {
                
throw new OrchardException(T("Your must enter a categoryname."));
            }

            _categoryRepository.Create(
new CategoryPartRecord { CategoryName = categoryName });

            
return "Product category created successfully!";
        }
        
        
/// <summary>
        
/// 在方法上加上
        
/// OrchardSwitches表示当前命名所要使用的交换参数
        
/// </summary>
        
/// <returns></returns>
        [CommandName("product create")]
        [CommandHelp(
"product create /Slug:<slug> /Title:<title> /Price:<price> /Brand:<brand> /CategoryName:<categoryName> [/Description:<description>]\r\n\t" + "Creates a new product")]
        [OrchardSwitches(
"Slug,Title,Price,Brand,CategoryName,Description")]
        
public string CreateProduct()
        {
            
if (!IsSlugValid(Slug))
            {
                
throw new OrchardException(T("Invalid Slug provided. Product creation failed."));
            }

            
double price = 0;
            
if (!double.TryParse(this.Price, out price))
            {
                
throw new OrchardException(T("Invalid Price provided. Product creation failed."));
            }

            CategoryPartRecord category 
= _categoryRepository.Get(x => x.CategoryName == CategoryName);
            
if (category == null)
            {
                
throw new OrchardException(T("Invalid CategoryName provided. Product creation failed."));
            }

            
//一个产品类型是由一个Route+Body+ProudctPart构成的
            var product = _contentManager.New("Product");
            product.As
<RoutePart>().Slug = Slug;
            product.As
<RoutePart>().Path = Slug;
            product.As
<RoutePart>().Title = Title;
            product.As
<RoutePart>().PromoteToHomePage = false;
            product.As
<BodyPart>().Text = this.Description;
            product.As
<ProductPart>().Brand = this.Brand;
            product.As
<ProductPart>().Price = price;
            product.As
<ProductPart>().Category = category;

            _contentManager.Create(product);

            
return "Product created successfully!";
        }

        
/// <summary>
        
/// 校验Route的简短友好值
        
/// </summary>
        
/// <param name="slug"></param>
        
/// <returns></returns>
        private static bool IsSlugValid(string slug)
        {
            
// see http://tools.ietf.org/html/rfc3987 for prohibited chars
            return slug == null || String.IsNullOrEmpty(slug.Trim()) || Regex.IsMatch(slug, @"^[^/:?#\[\]@!$&'()*+,;=\s]+$");
        }

    }

 

 

从上述代码中可以看出,为了能让Orchard命令行工具找到我们定义的命令,需要将ProductCommands继承于DefaultOrchardCommandHandler类。然后再执行相应命令的方法上加上CommandName属性来定义命令的名称,加上CommandHelp就可以定义命令的帮助。同时对于接收简单的命令参数时,我们可以直接在方法中添加参数。Orchard命令行工具会自动将相应命令后的字符串以空格为分隔分别给各个参数赋值。对于参数较多的情况下,我们可以在ProductCommands用定义定义多个加上OrchardSwitch的属性来接收值,定在相应的执行方法上加上OrchardSwitches属性定义该方法所用到的属性即可。

 

完成上述代码编写并编译项目后,我们就可以在Orchard命令行工具中输入:

  

Tips:对于输入的参数值有包含空格时,可以用引号包含参数值。如:/Title:”Office 2010”。

 

关于Orchard命令行工具的实现原理,可以查看Orchard.Commands命名空间下的相关类。Orchard.exe对应的项目为Orchard解决方案的Tools目录下的Orchard项目。等以后对这部分代码有深入学习和了解后再讲述Orchard命令行工具的实现原理吧。


代码下载点这里(解压安装nupkg)