用定制特性规范构件调用

     在GSP平台中,构件扮演着让平台更灵活,让用户需求更容易变化的重要角色,.net方法的调用,用户自定义窗体的展现等等都是最常见的应用场景。但由于我们的构件平台能力较弱,长久以来构件平台只是起着通用反射调用器的作用。让构件标准化,是我们发展构件平台的必经之路。这篇文章只是从使用定制特性这个角度来增强构件的标准化程度。

     定制特性从我的角度理解,就是给程序集、类型、方法、属性等等元素加上的辅助信息,我们可以告诉调用者调用前要做什么,调用后再做什么,或者是要让编译器做什么等等。我们经常使用的是.net framework中已经存在的特性,而自己定制特性的场景还很少。

     下面我描述一下我们在构件使用过程中的两个问题,并说明如何使用特性来解决:

1、在工作流的人工活动节点上,我们需要用户定义一个单据,作为人工执行工作的一个数据参考。这里需要传入一些参数(权限、取数条件、单据分类等等),我们的构件平台将窗体描述为构件,描述信息中包含了如何调用这个窗体的信息。但在实现时却有小小的限制,对于web窗体使用URL后跟参数的方式就可以很好的实现,而对于winform窗体,就必须要求与参数匹配的构造函数。但是很多单据的作者却更喜欢将这些参数实现为属性,而非构造函数中的参数。这样的情况我们除了强识别形参名称,并与窗体属性一致,就没有太好的办法。

2、与1中类似的情况,我们给这些构件的形参定义实参是,一般情况下是使用单据数据Schema中的字段,但这个过程也是把我们最终用户晕头转向,除非我们约定形参名称必须与Schema中的字段匹配,不然我们也不好解决这个问题。

     以上两个问题都可以用定制特性的方式,稍微优雅一些的解决。我们设计下面的特性:

[AttributeUsage(AttributeTargets.Property,AllowMultiple=false,Inherited=false)]
class GspParamsAttribute:Attribute
{
    private string paramName;

    public string ParamName
    {
        get { return paramName; }
        set { paramName = value; }
    }

    private string actualParamName;

    public string ActualParamName
    {
        get { return actualParamName; }
        set { actualParamName = value; }
    }

    private string actualParamPath;

    public string ActualParamPath
    {
        get { return actualParamPath; }
        set { actualParamPath = value; }
    }
}

[AttributeUsage(AttributeTargets.Class)]
class GspSupportParamSpecifyAttribute : Attribute
{
}

     对于单据的作者,就可以这样标记他的单据:

[GspSupportParamSpecify()]
class MyForm:Form
{
    private string someProperty;

    [GspParams(ParamName="SomeProperty",ActualParamName="OtherProPerty")]
    public string SomProperty
    {
        get { return someProperty; }
        set { someProperty = value; }
    }
}

     对于我们的构件设计器,就发现了一个需要在GSP平台中作为参数的属性SomProperty;对于流程设计在引用这个构件配参数时,就发现需要在Schema中找OtherProPerty字段作为实参来配置这个形参;对于构件调用的运行时,在发现GspSupportParamSpecify特性时,就知道这个类型中的某些属性需要被赋值,进而又从SomProperty属性上发现了GspParams特性,就知道使用哪个参数来给这个属性赋值了。

     而发现特性,需要使用反射,Type类型为我们提够了足够的信息,使用Attribute.GetCustomAttribute()的多个重载,可以方便我们运用于多个场景。

你可能感兴趣的:(用定制特性规范构件调用)