数据筛选和API优化。什么是扩张方法 (Extension Methods)?

by admin on 2018年10月5日

罗数据

急需:如果数据库被存在OrderNum相同,且IsDefault不同之笔录,那么IsDefault值为0的记录将为换值为1的笔录(IsDefault值为1的记录不显得)。

亚洲必赢手机入口 1

鉴于查阅出来的数量不多,100长中,所以自己是一直通查询及List内存中,然后以内存中进行数量过滤的操作,思来纪念去都觉得自身如下的贯彻方式要命low,但是自时以尚未悟出好的主意,不明白大家产生无发生好的章程?

            var newList = list.ToList();
            //筛选出哪些排序号有重复
            var orderNumList = newList.GroupBy(g => g.OrderNum).Select(g => new { orderNum = g.Key, count = g.Count() }).Where(g => g.count > 1).Select(s => s.orderNum).ToList();
            var cfList = newList.Where(w => orderNumList.Contains(w.OrderNum)); //获取有重复排序号的记录

            var cfDefaultList = cfList.Where(w => w.IsDefault);  //默认模块记录
            var cfNoDefaultList = cfList.Where(w => w.IsDefault == false); //非默认模块记录

            var intersectedList = from d in cfDefaultList join f in cfNoDefaultList on d.OrderNum equals f.OrderNum where d.IsDefault!= f.IsDefault select d;

            var newIntersectedList = intersectedList.Distinct().ToArray(); //排序号相同,既存在默认记录也存在非默认记录的数据 

                if (newIntersectedList != null && newIntersectedList.Length > 0)
                {
                    for (int i = 0; i < newIntersectedList.Length; i++)
                    {
                        if (newList.Contains(newIntersectedList[i]))
                        {
                            newList.Remove(newIntersectedList[i]);
                        }
                    }
                }
           newList = newList.OrderBy(x => x.OrderNum).ToList();

 以上之newList就代码截图中的数额。

英文原文链接:

优化API接口

起一个API接口时卡顿,而且死无平稳,快之时节2~3秒,慢的早晚10秒去矣。

接口需求:根据社区ID获取优惠券记录。

分析:

  • 顶为API接口提供数据的系遭到,缺少许多目录,存在多迟迟查询视图。
  • 原来的LINQ实现方式是在内存中分页,响应速度太慢。
  • 出现请求的景象下,资源占用。

优化思路:

http://weblogs.asp.net/scottgu/archive/2007/03/13/new-orcas-language-feature-extension-methods.aspx

1、使用缓存

同一个社区的人数在同一时间所盼的优惠券记录该是同一的,而且我们理应允许脏读,我们以12306方买火车票亚洲必赢手机入口的时刻,经常为会见看到显示出票,但是下单又没了,可能是运用了缓存,那么我们这边实在同样的得使用缓存来解决并发问题。

每当WebAPI上面加缓存,那么以分为客户端缓存和服务器缓存。而我辈理解,在ASP.NET
WebForm和ASP.NET
MVC中还是产生页面输出缓存的,而在WebAPI中默认没有,从NuGet上面下载WebApi.OutputCache.V2,然后再度API接口及添加 

[CacheOutput(ClientTimeSpan = 5)]//, ServerTimeSpan = 5

自我这里没法直接以服务器输出缓存,那是因无法捕获缓存变量参数。因为咱们API接口的请参数是string
appParam,字符串类型的,它是一个json对象上过base64各编码,然后再前进了url编码生成的字符串。

俺们只能解析后,获取社区ID,然后因社区ID来装缓存,把社区ID+
pageIndex就当做缓存的Key,考虑到要缓存的数据量很粗,这里自己直接使用.NET自带的缓存,引入命名空间:System.Web.Caching;

      private static System.Web.Caching.Cache ObjCache = HttpRuntime.Cache;
        /// <summary>
        /// 设置当前指定Key的Cache值,并限定过期时间 
        /// </summary>
        /// <param name="Key">缓存Key</param>
        /// <param name="Obj">缓存的值</param>
        /// <param name="TimeOuts">超时时间(秒)</param>
        public static void SetCacheSeconds(string Key, object Obj, double TimeOuts)
        {
            ObjCache.Insert(Key, Obj, null, System.DateTime.Now.AddSeconds(TimeOuts), TimeSpan.Zero);
        }
        /// <summary>
        /// 获取当前指定Key的Cache值
        /// </summary>
        /// <param name="Key">缓存Key</param>
        /// <returns>缓存的值</returns>
        public static object GetCache(string Key)
        {
            return ObjCache[Key];
        }

缓存操作类Cache完整代码如下:

亚洲必赢手机入口 2亚洲必赢手机入口 3

/*==================================
 * Author:
 * CreateTime:2014-7-15 17:26:29
 * Description:Cache操作类
 ===================================*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Caching;
using System.Runtime.CompilerServices;
using System.Web;
using System.Security.Policy;

namespace SSY.Util
{
    /// <summary>
    /// 缓存处理相关类
    /// </summary>
    public class Cache
    {
        private static System.Web.Caching.Cache ObjCache = HttpRuntime.Cache;
        private static short TimeOut = 720;

        #region 清除指定键值的缓存
        /// <summary>
        /// 清除指定键值的缓存
        /// </summary>
        /// <param name="Key">要清除的缓存的key值</param>
        public static void Clear(string Key)
        {
            if (ObjCache[Key] != null)
            {
                ObjCache.Remove(Key);
            }
        }
        #endregion

        #region 返回系统中缓存的个数
        /// <summary>
        /// 返回系统中缓存的个数
        /// </summary>
        /// <returns>缓存个数</returns>
        public static int Count()
        {
            return ObjCache.Count;
        }
        #endregion

        #region 获取当前指定Key的Cache值
        /// <summary>
        /// 获取当前指定Key的Cache值
        /// </summary>
        /// <param name="Key">缓存Key</param>
        /// <returns>缓存的值</returns>
        public static object GetCache(string Key)
        {
            return ObjCache[Key];
        }
        #endregion

        #region 设置当前指定Key的Cache值
        /// <summary>
        /// 设置当前指定Key的Cache值 
        /// </summary>
        /// <param name="Key">缓存Key</param>
        /// <param name="Obj">缓存的值</param>
        public static void SetCache(string Key, object Obj)
        {
            ObjCache.Insert(Key, Obj);
        }
        #endregion

        #region 设置当前指定Key的Cache值,并限定过期时间
        /// <summary>
        /// 设置当前指定Key的Cache值,并限定过期时间 
        /// </summary>
        /// <param name="Key">缓存Key</param>
        /// <param name="Obj">缓存的值</param>
        /// <param name="TimeOuts">超时时间(分钟)</param>
        public static void SetCache(string Key, object Obj, int TimeOuts)
        {
            ObjCache.Insert(Key, Obj, null, System.DateTime.Now.AddMinutes((double)TimeOuts), TimeSpan.Zero);
        }
        /// <summary>
        /// 设置当前指定Key的Cache值,并限定过期时间 
        /// </summary>
        /// <param name="Key">缓存Key</param>
        /// <param name="Obj">缓存的值</param>
        /// <param name="TimeOuts">超时时间(秒)</param>
        public static void SetCacheSeconds(string Key, object Obj, double TimeOuts)
        {
            ObjCache.Insert(Key, Obj, null, System.DateTime.Now.AddSeconds(TimeOuts), TimeSpan.Zero);
        }
        #endregion

        #region 设置当前指定Key的Cache值,依赖文件过期
        /// <summary>
        /// 设置当前指定Key的Cache值,依赖文件过期 
        /// </summary>
        /// <param name="Key">缓存Key</param>
        /// <param name="Obj">缓存的值</param>
        /// <param name="Files">相对地址,例如"~/files.xml"</param>
        public static void SetCache(string Key, object Obj, string Files)
        {
            CacheDependency cacheDep = new CacheDependency(System.Web.HttpContext.Current.Server.MapPath(Files),System.DateTime.Now);
            SetCache(Key, Obj, TimeOut, cacheDep, CacheItemPriority.High);
        }
        #endregion

        #region 设置当前指定Key的Cache值
        /// <summary>
        /// 设置当前指定Key的Cache值
        /// </summary>
        /// <param name="Key">缓存Key</param>
        /// <param name="Obj">缓存的值</param>
        /// <param name="Priority">撤销缓存的优先值,此参数的值取自枚举变量“CacheItemPriority”,优先级低的数据项将先被删除。此参数主要用在缓存退出对象时.</param>
        public static void SetCache(string Key, object Obj, CacheItemPriority Priority)
        {
            SetCache(Key, Obj, TimeOut, null, Priority);
        }
        #endregion

        #region 设置当前指定Key的Cache值
        /// <summary>
        /// 设置当前指定Key的Cache值
        /// </summary>
        /// <param name="Key">缓存Key</param>
        /// <param name="Obj">缓存的值</param>
        /// <param name="TimeOuts">一个TimeSpan,表示缓存参数将在多长时间以后被删除</param>
        /// <param name="CacheDep">缓存的依赖项,需要一个CacheDependency,可初始化一个</param>
        /// <param name="Priority">撤销缓存的优先值,此参数的值取自枚举变量“CacheItemPriority”,优先级低的数据项将先被删除。此参数主要用在缓存退出对象时</param>
        public static void SetCache(string Key, object Obj, int TimeOuts, CacheDependency CacheDep, CacheItemPriority Priority)
        {
            ObjCache.Insert(Key, Obj, CacheDep, System.DateTime.MaxValue, TimeSpan.FromHours((double)TimeOuts), Priority, null);
        }
        #endregion
    }
}

View Code

修改API接口代码:

           #region added by zouqj 2017-3-7
           var result = Util.Cache.GetCache(CommunityID+ pageIndex) as Result<List<GetAvailableCouponsModel>>;
           if (result==null) //不存在则写入缓存
           {
               //组装参数
               Dictionary<string, string> inParams = new Dictionary<string, string>();
               inParams.Add("UserId", userId);
               inParams.Add("PageIndex", pageIndex);
               inParams.Add("PageSize", pageSize);
               inParams.Add("CommunityID", CommunityID+ pageIndex);
               ...

               RequestParam RequestParam = GetRequestParam(methodName, inParams, AuthenticationId);
               var jsonContent = JsonConvert.SerializeObject(RequestParam);
               result = DoPost<List<GetAvailableCouponsModel>>(jsonContent, PostUrl);

               Util.Cache.SetCacheSeconds(CommunityID, result, 10); //写入缓存
           }
           return result;

哎是扩张方法(Extension
Method):

2、改吗存储过程实现

盖这个接口的事情逻辑比较复杂,之前的Linq代码写了好增长平十分失误,获取之记录数很多,而且要以内存中开展分页实现,所以自己以本的LINQ实现代码修改也分页存储过程实现。

存储过程代码如下:

亚洲必赢手机入口 4亚洲必赢手机入口 5

------------------------------------------创建领券中心存储过程 created by zouqj-2017-3-1-----------------------------------
IF EXISTS(Select Name From Sysobjects Where Name='usp_GetAvailableCoupons' And Xtype='P')
DROP PROCEDURE usp_GetAvailableCoupons
GO
CREATE PROC usp_GetAvailableCouponsl
(
@PageIndex int, --页码
@PageSize int, --每页容纳的记录数
@Sort NVARCHAR(50), --排序字段及规则,不用加order by
@hostName nvarchar(100),--服务器地址
@CommunityID UNIQUEIDENTIFIER, --社区
@IsGetCount BIT --是否得到记录总数,1为得到记录总数,0为不得到记录总数,返回记录集
)
AS
-------------------------------定义变量-----------------------
declare @strSql NVARCHAR(max);
DECLARE  @dt datetime2(7) --查询时间
SET @dt=GETDATE();
set nocount on;
----------------------------------------SQL开始--------------------------------------------无分类
IF @IsGetCount=1
BEGIN

SET @strSql=N'SELECT COUNT(*) FROM (SELECT DISTINCT t.CampaignID from
(SELECT 
c.ID AS CampaignID
 FROM MK_Campaign c WITH ( NOLOCK ) INNER JOIN MK_CouponConfig f WITH ( NOLOCK ) ON c.ID=f.CampaignID
           INNER JOIN MK_Coupon p WITH ( NOLOCK ) ON f.CouponID=p.ID
           WHERE f.CouponGetType=2 AND f.ReceiveStartTime <=@dt AND f.ReceiveEndTime>= @dt
           AND c.State=4 --执行中
           AND p.WholeNetwork=1 --全网优惠
UNION ALL
SELECT
    a.[ID] AS CampaignID
    FROM  [dbo].[MK_Campaign] AS a WITH ( NOLOCK )
        INNER JOIN [dbo].[MK_CouponConfig] AS b  WITH ( NOLOCK ) ON a.[ID] = b.[CampaignID]
        AND (b.[ReceiveStartTime] <= @dt) AND (b.[ReceiveEndTime] >= @dt) AND (2 = b.[CouponGetType]) AND (4 = a.[State]) 
        INNER JOIN [dbo].[MK_Coupon] AS c WITH ( NOLOCK ) ON b.[CouponID] = c.[ID]
        INNER JOIN [dbo].[MK_CouponRestriction] AS d  WITH ( NOLOCK ) ON c.[ID] = d.[CompainID]
        LEFT OUTER JOIN [dbo].[MK_CouponRestrictCategory] AS e WITH ( NOLOCK ) ON d.[ID] = e.[CouponRestrictionID]
        LEFT OUTER JOIN [dbo].[MK_CouponRestrictionOrg] AS f WITH ( NOLOCK ) ON d.[ID] = f.[CouponRestrictionID]
        INNER JOIN [dbo].[ViewOrganizationCommunityForInterface] AS v ON f.[OrgID] = v.[ID]    
    where v.CommunityID=@CommunityID  and 1 = d.[Type]
UNION ALL
SELECT 
   a.ID AS CampaignID
   FROM MK_Campaign a  WITH ( NOLOCK ) 
             INNER JOIN MK_CouponConfig b WITH ( NOLOCK ) ON a.ID=b.CampaignID AND (b.[ReceiveStartTime] <= @dt) AND (b.[ReceiveEndTime] >=@dt) 
             INNER JOIN [dbo].[MK_Coupon] AS c WITH ( NOLOCK ) ON b.[CouponID] = c.[ID] and (2 = b.[CouponGetType]) AND (4 = a.[State]) 
             INNER JOIN [dbo].[MK_CouponRestriction] AS d WITH ( NOLOCK ) ON c.[ID] = d.[CompainID]  AND (2 = d.[Type]) 
             LEFT OUTER JOIN MK_CouponRestrictionProduct AS e WITH ( NOLOCK ) ON d.[ID] = e.[CouponRestrictionID] 
             LEFT OUTER JOIN SL_Product AS f WITH ( NOLOCK ) ON (e.ProductID = f.ID)
             INNER JOIN ViewOrganizationCommunityForInterface v ON v.ID=f.PublisherID
   where v.CommunityID=@CommunityID
   ) t
 ) AS tt'
----------------------------------------------------------------------------------
END
ELSE
BEGIN
SET @strSql=N'SELECT DISTINCT t.* from(
SELECT 
          c.ID AS CampaignID,
          c.Name AS CampaignName,
          f.ValidityStartTime AS CampaignStartTime,
          f.ValidityEndTime AS CampaignEndTime,
          p.Name AS CouponsName,
          p.Price AS CouponsAmount,
          (CASE WHEN p.IsLimited =1 THEN 1 ELSE 2 END) AS IsLimited,
          p.FullAmount AS MinAmount,
          f.ValidityEndTime AS CouponsEndTime,
          f.ValidityStartTime AS CouponsStartTime,
          (CASE WHEN f.IsRepeateGet =1 THEN 1 ELSE 2 END) AS IsCanRepeatedReceive,
          f.ReceiveAddress AS ReceiveAddress,
          f.ReceiveEndTime AS ReceiveEndTime,
          f.ReceiveStartTime AS ReceiveStartTime,
          f.ReceiveMode AS ReceiveMethod,
          f.ProvideNum AS ReceiveNum,
          p.CreateTime AS CreateTime,
          p.Price AS Price,
          f.RemainCouponNum AS RemainCouponNum,
          f.ID AS CouponConfigId,
          p.WholeNetwork AS CouponsType,
          (CASE WHEN f.IconUrl IS NULL THEN N'''' WHEN f.IconUrl=N'''' THEN N'''' ELSE @hostName+f.IconUrl END) AS IconUrl 
FROM MK_Campaign c WITH ( NOLOCK ) 
                 INNER JOIN MK_CouponConfig f WITH ( NOLOCK ) ON c.ID=f.CampaignID
                 INNER JOIN MK_Coupon p WITH ( NOLOCK ) ON f.CouponID=p.ID
          WHERE f.CouponGetType=2 AND f.ReceiveStartTime <= @dt AND f.ReceiveEndTime>= @dt AND c.State=4 AND p.WholeNetwork=1 --全网优惠
--
UNION ALL
          SELECT a.[ID] AS CampaignID,
          a.[Name] AS CampaignName, 
          b.[ValidityStartTime] AS CampaignStartTime,
          b.[ValidityEndTime] AS CampaignEndTime, 
          c.[Name] AS CouponsName, 
          c.[Price] AS CouponsAmount, 
          CASE WHEN (c.[IsLimited] = 1) THEN 1 ELSE 2 END AS IsLimited, 
          c.[FullAmount] AS MinAmount, 
          b.[ValidityEndTime] AS CouponsEndTime, 
          b.[ValidityStartTime] AS CouponsStartTime, 
          CASE WHEN (b.[IsRepeateGet] = 1) THEN 1 ELSE 2 END AS IsCanRepeatedReceive, 
          b.[ReceiveAddress] AS [ReceiveAddress], 
          b.[ReceiveEndTime] AS [ReceiveEndTime], 
          b.[ReceiveStartTime] AS [ReceiveStartTime], 
          b.[ReceiveMode] AS ReceiveMethod, 
          b.[ProvideNum] AS ReceiveNum, 
          c.[CreateTime] AS CreateTime, 
          c.[Price] AS Price, 
          b.[RemainCouponNum] AS RemainCouponNum, 
          b.[ID] AS CouponConfigId, 
          e.[Type] AS CouponsType, 
          CASE WHEN (b.[IconUrl] = N'''' OR b.[IconUrl] IS NULL) THEN N'''' ELSE @hostName+b.[IconUrl] END AS IconUrl
                    FROM  [dbo].[MK_Campaign] AS a WITH ( NOLOCK )
                        INNER JOIN [dbo].[MK_CouponConfig] AS b  WITH ( NOLOCK ) ON a.[ID] = b.[CampaignID] AND (b.[ReceiveStartTime] <= @dt) AND (b.[ReceiveEndTime] >= @dt) AND (2 = b.[CouponGetType]) AND (4 = a.[State]) 
                        INNER JOIN [dbo].[MK_Coupon] AS c WITH ( NOLOCK ) ON b.[CouponID] = c.[ID]
                        INNER JOIN [dbo].[MK_CouponRestriction] AS d  WITH ( NOLOCK ) ON c.[ID] = d.[CompainID]
                        LEFT OUTER JOIN [dbo].[MK_CouponRestrictCategory] AS e WITH ( NOLOCK ) ON d.[ID] = e.[CouponRestrictionID]
                        LEFT OUTER JOIN [dbo].[MK_CouponRestrictionOrg] AS f WITH ( NOLOCK ) ON d.[ID] = f.[CouponRestrictionID]
                        INNER JOIN [dbo].[ViewOrganizationCommunityForInterface] AS v ON f.[OrgID] = v.[ID]    
                    where v.CommunityID=@CommunityID  and 1 = d.[Type]
UNION ALL
SELECT 
       a.ID AS CampaignID,
       a.Name AS CampaignName,
       b.ValidityStartTime AS CampaignStartTime,
       b.ValidityEndTime AS CampaignEndTime,
       c.Name AS CouponsName,
       c.Price AS CouponsAmount,
       (CASE WHEN c.IsLimited=1 then 1 else 2 END) AS IsLimited,
       c.FullAmount AS MinAmount,
       b.ValidityEndTime AS CouponsEndTime,
       b.ValidityStartTime AS CouponsStartTime,
       (case when b.IsRepeateGet=1 then 1 else 2 END) AS IsCanRepeatedReceive,
       b.ReceiveAddress AS ReceiveAddress,
       b.ReceiveEndTime AS ReceiveEndTime,
       b.ReceiveStartTime AS ReceiveStartTime,
       b.ReceiveMode AS ReceiveMethod,
       b.ProvideNum AS ReceiveNum,
       c.CreateTime AS CreateTime,
       c.Price AS Price,
       b.RemainCouponNum AS RemainCouponNum,
       b.ID AS CouponConfigId,
       d.[TYPE] AS CouponsType,
       (CASE WHEN b.IconUrl IS NULL THEN N'''' WHEN b.IconUrl=N'''' THEN N'''' ELSE @hostName+b.IconUrl END) AS IconUrl
   FROM MK_Campaign a  WITH ( NOLOCK ) 
                    INNER JOIN MK_CouponConfig b WITH ( NOLOCK ) ON a.ID=b.CampaignID AND (b.[ReceiveStartTime] <= @dt) AND (b.[ReceiveEndTime] >= @dt) 
                    INNER JOIN [dbo].[MK_Coupon] AS c WITH ( NOLOCK ) ON b.[CouponID] = c.[ID] and (2 = b.[CouponGetType]) AND (4 = a.[State]) 
                    INNER JOIN [dbo].[MK_CouponRestriction] AS d WITH ( NOLOCK ) ON c.[ID] = d.[CompainID]  AND (2 = d.[Type]) 
                    LEFT OUTER JOIN MK_CouponRestrictionProduct AS e WITH ( NOLOCK ) ON d.[ID] = e.[CouponRestrictionID] 
                    LEFT OUTER JOIN SL_Product AS f WITH ( NOLOCK ) ON (e.ProductID = f.ID)
                    INNER JOIN ViewOrganizationCommunityForInterface v ON v.ID=f.PublisherID
                    where v.CommunityID=@CommunityID
   ) t
ORDER BY t.Price--@Sort
offset (@PageIndex-1)*@PageSize ROWS  FETCH NEXT @PageIndex*@PageSize ROWS ONLY'
end
--执行SQL
exec sp_executesql @strSql,N'@PageIndex int,@PageSize int,@Sort nvarchar(50),@hostName nvarchar(100),@CommunityID UNIQUEIDENTIFIER,@IsGetCount bit,@dt datetime2(7)',@PageIndex =@PageIndex,@PageSize =@PageSize,@Sort=@Sort,@hostName=@hostName,@CommunityID=@CommunityID,@IsGetCount=@IsGetCount,@dt=@dt
set nocount off;

View Code

此间要小心的凡,存储执行是,先关计数,set nocount on;,然后再打开set
nocount off;,这样好升级性。还有即使是运用WITH ( NOLOCK
)允许脏读,提升查询效率。

此处碰到一个生奇异的问题,我使用exec
sp_executesql
@strSql,N’….’的点子来施行是不曾问题的,而一旦我下拼接sql的法门,会报错,因为sql字符串被截断了,只截取到了4000只字符长度,即便我管字符串变量长度设置也nvarchar(max)也并未因此。

分页方式下Sqlserver2012以上版本才支撑之飞方式:offset … FETCH NEXT
…ROWS ONLY

本来Linq的执行时测试:

亚洲必赢手机入口 6BLW.png)亚洲必赢手机入口 7

自我修改也存储过程后的实施时间测试:

亚洲必赢手机入口 8

性能差距甚肯定。

扩大方法允许开发人员往一个存世的CLR类型的公然契约(contract)中补充加新的法,而未用生成子类或者另行编译原来的门类。扩展方法推进将今天动态语言中风行的对duck
typing的支持之灵活性,与强类型语言的性与编译时证实融合起来。

扩展方法促成了森管用之动状况,并而在作Orcas一部分颁发之.NET版本中推介的死去活来强大的LINQ查询框架成为可能。

简言之的扩充方法例子:

来没出纪念了如检查一个字符串变量是否是个官方的电子邮件地址?
在今日,你大概需要通过调用一个单独的近乎(或许通过一个静态方法)来促成检查该字符串变量是否合法。譬如,象这样:

 

string email = Request.QueryString[“email”];

if ( EmailValidator.IsValid(email)
) {
   
}

 

而使用C#同VB中的新“扩展方法”语言特色的言语,我虽然好加上一个中的“IsValidEmailAddress()”方法及string类本身遭到错过,该方式返回时字符串实例是否是只法定的字符串。然后自己得以管自身之代码重写一下,使的更加干净,而且再也兼具描述性,象这样:

 

string email = Request.QueryString[“email”];

if ( email.IsValidEmailAddress()
) {
   
}

 

咱们是怎管这个新的IsValidEmailAddress()方法上加到存活的string类里去之啊?我们是通过定义一个静态的门类,带有我们的“IsValidEmailAddress”这个静态的法来落实的,象下这样:

 

public static class ScottGuExtensions
{
    public static bool IsValidEmailAddress(this string s)
    {
        Regex regex = new Regex(@”^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$”);
        return regex.IsMatch(s);
    }
}

 

小心,上面的静态方法在率先个档次是string的参数变量前发生个“this”关键词,这告诉编译器,这个一定的扩大方法应该加上到路也“string”的对象吃失去。然后于IsValidEmailAddress()方法实现里,我可以拜调用该方法的实际上string实例的享有公开属性/方法/事件,取决于它是否是法定电子邮件地址来回到true/false。

于自我的代码里拿这个一定的扩张方法的贯彻增长到string实例,我一旦采取专业的“using”语句来引入含有该扩展方法的兑现之命名空间:

 

using ScottGuExtensions;

 

然后编译器就见面以另外string上正确地定位IsValidEmailAddress()方法。在当面发行的Orcas三月份的CTP中的C#同VB在Visual
Studio代码编辑器里对扩大方法供了整的intellisense支持。所以,当我以一个字符串变量上点击“.”关键词时,我的恢弘方法现在便会见产出于intellisense的下拉框里:

亚洲必赢手机入口 9

VB和C#编译器也会见特别当然地叫跟汝对所有扩展方法用法的编译时之自我批评,这意味你会获一个编译时误,假如你键错或者错用一个扩张方法的口舌。

[感谢David
Hayden
举凡他在去年之一个老帖子
里首先独示范了自以方下的是IsValidEmailAddress使用状况。]

扩大方法以状况续…

运用扩展方法是新特点来叫各自品种丰富方法给开发人员开辟了诸多实用之扩展性使用状况。但令扩展方法十分强大的是,它们不仅能运用至个别项目上,也会采用到.NET框架中其他基类或接口及。这允许开发人员建立种种可用于整个.NET框架的长的只是整合的框架层扩展。

像,考虑这样一个景象,我想使一个既爱,描述性又大的点子来检查一个对象是否曾经包含在一个靶集合或数组里。我可以定义一个简易的.In(集合)扩展方法,我想把它长到.NET框架中之有着目标上,我可当C#里如此来兑现这“In()”扩展方法:

亚洲必赢手机入口 10

注意点我是怎样声明扩展方法的率先只参数的:“this object
o”。这标志,这个扩展方法应该适用于继续给基类System.Object的备品种,这意味著我可以于.NET中之每个对象上运其。

点这个“In”方法的贯彻允许自己检查一个点名的靶子是否含有在作艺术参数传入的一个IEnumerable序列中。因为具有的.NET集合和数组都实现了IEnumerable接口,现在本身具备了一个实惠的,描述性强的法子来检查一个任意的靶是否属任何.NET集合或数组。

接下来自己不怕可以以这个“In()”方法来拘禁一个一定的字符串是否当一个字符串数组中:

亚洲必赢手机入口 11

自我耶可以用它来检查一个一定的ASP.NET控件是否以一个器皿控件集合里:

亚洲必赢手机入口 12

自竟可以那个所以在象整数这样的标量数据类型上:

亚洲必赢手机入口 13

留神点,你还是可在象整数值42如此的骨干数据列值达到使扩展方法。因为CLR支持数值类的自发性boxing/unboxing,扩展方法可一直使用在数值与另标量数据类型上。

汝大概可以开始起地方的例证中扣有,扩展方法可以招一些非常丰富和描述性强之扩展性使用状况。当以于.NET中普遍的基类和接口及经常,他们可以引致一些可怜好的特定于有世界(domain
specific)的框架和做使用状况。

放开的System.Linq扩展方法

一个以Orcas时段随.NET发布之置的扩充方法库是同一法允许开发人员对其它数进行查询的好强劲的询问扩展方法。这些扩展方法实现在新的
System.Linq
命名空间之下,定义了正规的查询操作符扩展方法,可以为.NET开发人员用来轻松地查询XML,关系数据库,.NET
对象, 和另外其他数据结构类型。(So this is the LINQ…)

下面是应用这些查询扩展方法的扩展性模型的几乎独好处:

1)
它同意一个可用于拥有数据类型(数据库,XML文件,内存中的目标,以及web-services等)的同之询问编程模型与语法。

2)
它是足以做的,允许开发人员轻松地为查询语法中上加新的点子/操作符。譬如,我们可将我们于定义的“In()”方法和为LINQ所定义之科班的“Where()”方法作为一个单身查询的同一组成部分共下。我们于定义的In()方法看起来就是和由System.Linq命名空间供的正规方法同样。

3)
它是只是扩大的,允许和外数据提供器类型一起利用。譬如,任何一个象NHibernate或LLBLGen这样现有的ORM引擎可以兑现LINQ的正规化查询操作符来允许对她们共处的ORM实现与投引擎实现LINQ查询。这允许开发人员学会一个询问数据的共同方式,然后针对项目繁多的增长多少存储实现以相同的技术。

自身拿当生几乎个礼拜里对LINQ作更多的示范,但想留您几只例,这些事例展示了争对不同品种的数据运用几个放置的LINQ查询扩展方法:

应用状况一样:对内存中的.NET对象下LINQ扩展方法

要是我们模样这样定义了象征“Person”的好像:

亚洲必赢手机入口 14

然后我好行使新的对象初始化器和集纳初始化器特性创立和填充一个“people”集合,象这样:

亚洲必赢手机入口 15

然后我可采取由System.Linq提供的正经的“Where()”扩展方法来得到之集中FirstName的首字符是”S”的那些“Person”对象,象这样:

亚洲必赢手机入口 16

点这新的 p => 语法是“Lambda表达式”的一个例子,是针对C#
2.0伏叫作艺术支持的又强烈的提高,允许我们由此一个实参来轻松地表达查询过滤(在此情形下,我们代表我们仅想使回去一错firstname属性的首字符是“S”字母之Person对象)
。上面这查询然后即会见回去包含2只目标的队列,Scott 和 Susanne。

自己吗足以使由System.Linq提供的初的“Average”
和“Max”扩展方法修代码来控制自之集合里的口的平均年龄,以及年龄最要命之丁,象这样:

亚洲必赢手机入口 17

使状况二:对XML文件使用LINQ扩展方法

乃手工在内存里创建一个硬写(hard-coded)的数目集合大概是杀少见的。更发出或的凡,你会打一个XM文件,数据库,或web服务里获取数据。

如若我们以硬盘上发出一个XML文件,包含下面这样的数量:

亚洲必赢手机入口 18

非常明确地,我可以运用现有的 System.Xml APIs
来装这个XML文件上一个DOM,然后访问它,或者应用一个层次较逊色的XmlReader
API ,自己对的手工分析。或者,在
Orcas中,我现为堪下支持标准的LINQ扩展方法的System.Xml.Linq 实现(即
XLINQ),更优雅地分析和处理XML。

脚的代码例子展示了怎么使用LINQ来获得有包含一个子节点的值的首字母为“S”的<person>
XML元素:

亚洲必赢手机入口 19

顾,它采取了跟内存中对象例子中千篇一律模型一样的 Where()
扩展方法。现在她回到一个“XElement”元素序列,XElemen是未曾路的XML节点元素。或者我啊得更写查询表达式,通过LINQ的
Select()
扩展方法来布局数据形状,提供一个行使了新的目标初始化器句法的Lambda
表达式来填充同样的“Person”类,跟咱们率先只内存中的联谊的例子一样:

亚洲必赢手机入口 20

面的代码会召开用打开,分析,和过滤XML,然后回一个强类型的Person对象序列所有的办事,不需要什么映射或持久的文书来映射数值,我只是当上面的LINQ查询式里一直指明了自XML到对象的构形而已。

我哉堪与眼前一样以同一的Average() 和 Max()
LINQ扩展方法来计量XML文件中<person>元素的平均年龄,以及最充分岁,象这样:

亚洲必赢手机入口 21

我决不手工分析XML文件,XLINQ
不仅可呢己处理分析,它在估算LINQ表达式时,也得使低层的XMLReader,而未是以DOM来分析文件。这意味它们是快捷的太,而且不分配很多内存。

动状况三:对数据库使用LINQ扩展方法

万一我们有着一个SQL数据库,内含一个吃“People”的阐明,具有下列数定义:

亚洲必赢手机入口 22

自身好用Visual Studio中初的LINQ到SQL的所见即所得(WYSIWYG)
ORM设计器,快速地开创一个射到数据库的“Person”类:

亚洲必赢手机入口 23

下一场自己好应用自先用来对象以及XML文件一律的LINQ Where()
扩展方法,从数据库中赢得firstname的首字符为“S”的强类型“Person”对象序列:

亚洲必赢手机入口 24

只顾,查询句法与对象以及XML场景中的相同模一样。

然后自己吗得使与前面一样的 LINQ Average() 和Max()
扩展方法来起数据库里落平均与极端酷价值,象这样:

亚洲必赢手机入口 25

若而地方代码例子工作,你自己未待编写任何SQL代码。Orcas中提供的LINQ到SQL对象关系映射器会处理获,跟踪,和创新映射到您的数据库数据定义及存储过程的对象。你如果利用任何LINQ扩展方法对结果开展过滤跟构形即可,LINQ到SQL会实施获取数据所用的SQL代码(注意,上面的
Average和Max
扩展方法充分扎眼地无见面从数据表中归所有的数据实施,它们会采取TSQL的聚合函数来计算数据库被的值,然后才回一个标量值)。

呼吁看我一月份打的一个拍照,演示了LINQ到SQL如何强烈地改善了Orcas中之数据生产力。录像中,你为堪看看新的LINQ到SQL的所见即所得ORM设计器的实战示范,以及对数据模型编写LINQ代码时代码编辑器提供的完好的
intellisense。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图