如何写兼容SharePoint Server和SharePoint Foundation的代码

        一般来说,我们的代码如果需要运行在SharePoint Foundation上面,在SharePoint Foundation的环境中开发是最方便的;如果需要运行在SharePoint Server上面,在SharePoint Server的环境中开发是最方便的。如果我们的代码需要同时兼容SharePoint Server和Foundation的话,我们应该在SharePoint Server上进行开发,想要代码运行在SharePoint Foundation平台上,要额外考虑几个问题。

        首先就是判断当前SharePoint是Server版本还是Foundation版本的。最精确的判断方法是检查注册表中的SharePoint产品ID,可以参考这篇文章
但是查注册表比较麻烦,简单的方法是可以直接从代码获得当前SharePoint的product id,然后在产品的ID列表中查找就好了,以下是代码:

bool IsSharePointServer(){
    // B2C0B444-3914-4ACB-A0B8-7CF50A8F7AA0 : SharePoint Server 2010 Standard Trial
    // 3FDFBCC8-B3E4-4482-91FA-122C6432805C : SharePoint Server 2010 Standard
    // 88BED06D-8C6B-4E62-AB01-546D6005FE97 : SharePoint Server 2010 Enterprise Trial
    // D5595F62-449B-4061-B0B2-0CBAD410BB51 : SharePoint Server 2010 Enterprise
    Guid[] serverGuids = { new Guid("B2C0B444-3914-4ACB-A0B8-7CF50A8F7AA0"), 
                       new Guid("3FDFBCC8-B3E4-4482-91FA-122C6432805C"), 
                       new Guid("88BED06D-8C6B-4E62-AB01-546D6005FE97"), 
                       new Guid("D5595F62-449B-4061-B0B2-0CBAD410BB51") };

    // If a Server ID cannot be detected we are running on Foundation.
    bool isServer =  SPFarm.Local.Products.Any(productGuid => serverGuids.Contains(productGuid));
    return isServer
}
        这个方法优点是非常精确,缺点是比较麻烦,需要查找SharePoint产品的ID,如果既支持2010,又要支持2013,就要查不同的产品ID,写不同的代码。

        第二个判断当前SharePoint是Server版本还是Foundation版本的方法是查找Farm中的feature定义,有些feature是Server中存在而Foundation中不存在的。例如有个Publishing feature。因此可以通过判断这个feature是否存在来判断是Server版本还是Foundation版本。这个方法的优点是简单,而且不论SharePoint 2010还是2013,都可以用。但是不保证后面的版本比如出了2015,会不会把这个feature加到Foundation中,因此保险的做法是多判断几个Foundation中没有的feature,以下是代码(使用了Publishing和TemplateDiscovery这两个feature):

bool IsSharePointServer(){
    bool isServer = false;
    SPFeatureDefinitionCollection features = SPFarm.Local.FeatureDefinitions;
    if (features["Publishing"] != null && features["TemplateDiscovery"] != null)
    {
        isServer= true;
    }
    return isServer;
}

        第二个需要考虑的问题就是一些程序集是只有Server版本上才有的,例如支持Metadata的程序集Microsoft.SharePoint.Taxonomy,在Foundation中是找不到的,但是这并不影响开发,因为我们在Server上开发,所以VS可以引用这个程序集,也可以正常使用其中的类,编译也没有问题。问题在于,这样写出来的代码,在Foundation上运行会出现无法找到dll的错误,导致代码无法使用。解决的办法就是,在写代码的时候,需要判断当前的SharePoint是Server版本还是Foundation版本的,如果是Foundation版本,就不要运行这类代码,举个例子:

void DoSomethingOnBothServerAndFoundation()
{
    if(IsSharePointServer())
    {
        //Server
        TaxonomyField taxField = ...; //TaxonomyField是在Microsoft.SharePoint.Taxonomy.dll中定义的,这里需要加载程序集
    }
    else
    {
        //Foundation
        ...
    }
}
        写好这样的代码之后,编译部署,在Server上运行,都没有问题,但是放到Foundation上运行,还是会报出无法找到dll的错误(An exception has occurred.   ExceptionType: 'FileNotFoundException'   ExceptionMessage: 'Could not load file or assembly 'Microsoft.SharePoint.Taxonomy, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' or one of its dependencies. The system cannot find the file specified.')。原因在于运行时,JIT在编译一个方法的时候,它会载入这个方法中引用的所有类型所在的程序集。因此JIT在编译这个方法的时候,不论代码中有没有判断当前的SharePoint是Server还是Foundation,都会去载入Microsoft.SharePoint.Taxonomy程序集,因此在Foundation上运行失败。解决办法是针对不同的平台写不同的方法,在调用方法之前做判断。

void DoSomethingOnBothServerAndFoundation()
{
    if(IsSharePointServer())
    {
        Method_Server();
    }
    else
    {
        Method_Foundation();
    }
}

void Method_Server()
{
    //Server
    TaxonomyField taxField = ...; //TaxonomyField是在Microsoft.SharePoint.Taxonomy.dll中定义的,这里加载程序集
    ... ...
}

void Method_Foundation()
{
    //Foundation
    ... ...
}


这样的话,方法“Method_Server()”在Foundation环境上就不会运行,JIT也不会试图加载Microsoft.SharePoint.Taxonomy.dll,也不会出错了,就可以正常的运行在Server和Foundation上了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值