ASP.NET MVC 开源项目Kigg解读(2)——Kigg.Core第一部分

Kigg是一个很好的ASP.NET MVC范例项目,本着研究的目的,对Kigg进行解读。

上一篇中,我们介绍了Kigg的启动、后台任务和事件聚合器。这一篇,我们来看看Kigg的核心类库Kigg.Core

一、类库一览

Kigg.Core是Kigg的灵魂所在,主要包含:

  • ConfigurationSettings:站点设置
  • DomainObjects:领域模型
  • Extension:对.NET对象的扩展
  • Helper:一些帮助方法
  • Infrastructure:基础架构
  • Repository:数据访问
  • Service:数据服务

二、杂项     在想到底用什么来描述ConfigurationSettings,Extension,Helper,第一印象是杂项,那么就叫杂项吧!ORZ~ 1、配置信息     ConfigurationSettings其实是Kigg的站点配置信息:

  Kigg是通过在Unity的配置文件中来设置这些配置信息的

   1:                         <type type="IConfigurationSettings" mapTo="ConfigurationSettings">
   2:                          <lifetime type="Singleton"/>
   3:                          <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
   4:                              <property name="RootUrl" propertyType="System.String">
   5:                                  <value type="System.String" value="http://localhost:4252"/>
   6:                              </property>
   7:                              <property name="WebmasterEmail" propertyType="System.String">
   8:                                  <value type="System.String" value=""/>
   9:                              </property>
  10:                              // 省略……
  11:                          </typeConfig>
  12:                      </type>

2、Extension

再来看Extension:

Extension包含了对集合、枚举对象、Guid、DateTime以及String的扩展,有兴趣的同学可以去看看。

第一篇中的ForEach就来自于EnumerableExtension

   1:      public static class EnumerableExtension
   2:      {
   3:          [DebuggerStepThrough]
   4:          public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
   5:          {
   6:              foreach (T item in enumerable)
   7:              {
   8:                  action(item);
   9:              }
  10:          }
  11:      }

3、Helper

最后看看Helper

这里包含了一些帮助类库:

CheckArgument是参数检验,比如:

   1:   
   2:              [DebuggerStepThrough]
   3:              public static void IsNotEmpty(Guid argument, string argumentName)
   4:              {
   5:                  if (argument == Guid.Empty)
   6:                  {
   7:                      throw new ArgumentException("\"{0}\" cannot be empty guid.".FormatWith(argumentName), argumentName);
   8:                  }
   9:              }

CheckArgument广泛的运用在Kigg.Core的方法中,比如第一部分中的

   1:  public StartBackgroundTasks(IBackgroundTask[] tasks) 
   2:  {
   3:      Check.Argument.IsNotEmpty(tasks, "tasks"); 
   4:      _tasks = tasks;  10:          
   5:  }

    PagedResult是个有意思的玩意,如果你使用过Subsonic,你会发现这个和PagedList有点像。PagedResult在Kigg中作为获取列表方法的返回类型,包含了结果集和总记录数,因此分页就比较方便了。

   1:   public class PagedResult<T>
   2:      {
   3:          private readonly ReadOnlyCollection<T> _result;
   4:          private readonly int _total;
   5:   
   6:          public PagedResult(IEnumerable<T> result, int total)
   7:          {
   8:              Check.Argument.IsNotNull(result, "result");
   9:              Check.Argument.IsNotNegative(total, "total");
  10:   
  11:              _result = new ReadOnlyCollection<T>(new List<T>(result));
  12:              _total = total;
  13:          }
  14:   
  15:          public PagedResult() : this(new List<T>(), 0)
  16:          {
  17:          }
  18:   
  19:          public ICollection<T> Result
  20:          {
  21:              [DebuggerStepThrough]
  22:              get
  23:              {
  24:                  return _result;
  25:              }
  26:          }
  27:   
  28:          public int Total
  29:          {
  30:              [DebuggerStepThrough]
  31:              get
  32:              {
  33:                  return _total;
  34:              }
  35:          }
  36:   
  37:          public bool IsEmpty
  38:          {
  39:              [DebuggerStepThrough]
  40:              get
  41:              {
  42:                  return _result.Count == 0;
  43:              }
  44:          }
  45:      }

三、基础架构

话说,这一块是Kigg比较核心的部分。

这里包含了前面提到的Boot、BackgroundTask和EventAggrator,在这里就不再多说了。

1、IOC

    IOC是Kigg的基石,大部分的类的实例化和状态维持都由它来实现。Kigg使用Unity来作为IOC工具,想要简单的话,直接使用Unity就可以了,但是为了解除与Unity的依赖,Kigg特地抽象出一个接口IDependencyResolver:

   1:   public interface IDependencyResolver : IDisposable
   2:      {
   3:          void Register<T>(T instance);
   4:   
   5:          void Inject<T>(T existing);
   6:   
   7:          T Resolve<T>(Type type);
   8:   
   9:          T Resolve<T>(Type type, string name);
  10:   
  11:          T Resolve<T>();
  12:   
  13:          T Resolve<T>(string name);
  14:   
  15:          IEnumerable<T> ResolveAll<T>();
  16:      }

这样,不管使用什么IOC工具,只需要实现这个接口就可以了。

在没用IOC的时候,要创建一个借口的实例怎么做?用工厂模式呗!这样在AppSetting中配置下dependencyResolverTypeName就可以了

   1:      public interface IDependencyResolverFactory
   2:      {
   3:          IDependencyResolver CreateInstance();
   4:      }
   5:     public class DependencyResolverFactory : IDependencyResolverFactory
   6:      {
   7:          private readonly Type _resolverType;
   8:   
   9:          public DependencyResolverFactory(string resolverTypeName)
  10:          {
  11:              Check.Argument.IsNotEmpty(resolverTypeName, "resolverTypeName");
  12:   
  13:              _resolverType = Type.GetType(resolverTypeName, true, true);
  14:          }
  15:   
  16:          public DependencyResolverFactory() : this(new ConfigurationManagerWrapper().AppSettings["dependencyResolverTypeName"])
  17:          {
  18:          }
  19:   
  20:          public IDependencyResolver CreateInstance()
  21:          {
  22:              return Activator.CreateInstance(_resolverType) as IDependencyResolver;
  23:          }
  24:      }

为了方便使用IOC,Kigg特定创建了一个静态类库IOC:

   1:  public static class IoC
   2:      {
   3:          private static IDependencyResolver _resolver;
   4:   
   5:          [DebuggerStepThrough]
   6:          public static void InitializeWith(IDependencyResolverFactory factory)
   7:          {
   8:              Check.Argument.IsNotNull(factory, "factory");
   9:   
  10:              _resolver = factory.CreateInstance();
  11:          }
  12:   
  13:          [DebuggerStepThrough]
  14:          public static void Register<T>(T instance)
  15:          {
  16:              Check.Argument.IsNotNull(instance, "instance");
  17:   
  18:              _resolver.Register(instance);
  19:          }
  20:   
  21:          [DebuggerStepThrough]
  22:          public static void Inject<T>(T existing)
  23:          {
  24:              Check.Argument.IsNotNull(existing, "existing");
  25:   
  26:              _resolver.Inject(existing);
  27:          }
  28:   
  29:          [DebuggerStepThrough]
  30:          public static T Resolve<T>(Type type)
  31:          {
  32:              Check.Argument.IsNotNull(type, "type");
  33:   
  34:              return _resolver.Resolve<T>(type);
  35:          }
  36:   
  37:          [DebuggerStepThrough]
  38:          public static T Resolve<T>(Type type, string name)
  39:          {
  40:              Check.Argument.IsNotNull(type, "type");
  41:              Check.Argument.IsNotEmpty(name, "name");
  42:   
  43:              return _resolver.Resolve<T>(type, name);
  44:          }
  45:   
  46:          [DebuggerStepThrough]
  47:          public static T Resolve<T>()
  48:          {
  49:              return _resolver.Resolve<T>();
  50:          }
  51:   
  52:          [DebuggerStepThrough]
  53:          public static T Resolve<T>(string name)
  54:          {
  55:              Check.Argument.IsNotEmpty(name, "name");
  56:   
  57:              return _resolver.Resolve<T>(name);
  58:          }
  59:   
  60:          [DebuggerStepThrough]
  61:          public static IEnumerable<T> ResolveAll<T>()
  62:          {
  63:              return _resolver.ResolveAll<T>();
  64:          }
  65:   
  66:          [DebuggerStepThrough]
  67:          public static void Reset()
  68:          {
  69:              if (_resolver != null)
  70:              {
  71:                  _resolver.Dispose();
  72:              }
  73:          }
  74:      }

    在使用的使用,需要先调用IoC.InitializeWith(),初始化IoC内部的静态字段_resolver,然后就可以直接方便的使用IOC了,回顾第一篇的代码:

   1:    public static class Bootstrapper
   2:      {
   3:          static Bootstrapper()
   4:          {
   5:              try
   6:              {
   7:                  IoC.InitializeWith(new DependencyResolverFactory());
   8:              }
   9:              catch (ArgumentException)
  10:              {
  11:                  // Config file is Missing
  12:              }
  13:          }
  14:  
  15:          public static void Run()
  16:          {
  17:              IoC.ResolveAll<IBootstrapperTask>().ForEach(t => t.Execute());
  18:          }
  19:      }

2、缓存

   缓存组件很多,Kigg选用的是Enterprise Library。同样的为了消除与缓存组件的依赖,Kigg定义了自己的缓存接口:

   1:  public interface ICache
   2:      {
   3:          int Count
   4:          {
   5:              get;
   6:          }
   7:   
   8:          void Clear();
   9:   
  10:          bool Contains(string key);
  11:   
  12:          T Get<T>(string key);
  13:   
  14:          bool TryGet<T>(string key, out T value);
  15:   
  16:          void Set<T>(string key, T value);
  17:   
  18:          void Set<T>(string key, T value, DateTime absoluteExpiration);
  19:   
  20:          void Set<T>(string key, T value, TimeSpan slidingExpiration);
  21:   
  22:          void Remove(string key);
  23:      }

    同样的,为了方便调用,Kigg创建了Cache静态类,这次,采用的是一个静态属性,注意下InternalCache是通过IOC初始化的。这样,只需要在IOC的配置文件中指定下哪个具体的类实现了ICache接口就可以了。

   1:  public static class Cache
   2:      {
   3:          public static int Count
   4:          {
   5:              [DebuggerStepThrough]
   6:              get
   7:              {
   8:                  return InternalCache.Count;
   9:              }
  10:          }
  11:   
  12:          private static ICache InternalCache
  13:          {
  14:              [DebuggerStepThrough]
  15:              get
  16:              {
  17:                  return IoC.Resolve<ICache>();
  18:              }
  19:          }
  20:   
  21:          [DebuggerStepThrough]
  22:          public static void Clear()
  23:          {
  24:              InternalCache.Clear();
  25:          }
  26:   
  27:          [DebuggerStepThrough]
  28:          public static bool Contains(string key)
  29:          {
  30:              Check.Argument.IsNotEmpty(key, "key");
  31:   
  32:              return InternalCache.Contains(key);
  33:          }
  34:   
  35:          [DebuggerStepThrough]
  36:          public static T Get<T>(string key)
  37:          {
  38:              Check.Argument.IsNotEmpty(key, "key");
  39:   
  40:              return InternalCache.Get<T>(key);
  41:          }
  42:   
  43:          [DebuggerStepThrough]
  44:          public static bool TryGet<T>(string key, out T value)
  45:          {
  46:              Check.Argument.IsNotEmpty(key, "key");
  47:   
  48:              return InternalCache.TryGet(key, out value);
  49:          }
  50:   
  51:          [DebuggerStepThrough]
  52:          public static void Set<T>(string key, T value)
  53:          {
  54:              Check.Argument.IsNotEmpty(key, "key");
  55:   
  56:              InternalCache.Set(key, value);
  57:          }               // 以下省略
   84:      }

3、日志

     日志和缓存同样一个道理,有一个Log接口

   1:  public interface ILog
   2:      {
   3:          void Info(string message);
   4:   
   5:          void Warning(string message);
   6:   
   7:          void Error(string message);
   8:   
   9:          void Exception(Exception exception);
  10:      }

      然后一个静态类Log,这里没有用一个静态的字段或属性来缓存ILog接口,而是一个GetLog()方法,效率上不如前面的Cache,算是一个小瑕疵吧。

   1:  public static class Log
   2:      {
   3:          [MethodImpl(MethodImplOptions.NoInlining)]
   4:          [DebuggerStepThrough]
   5:          public static void Info(string message)
   6:          {
   7:              Check.Argument.IsNotEmpty(message, "message");
   8:   
   9:              GetLog().Info(message);
  10:          }
  11:   
  12:         // 省略部分代码      
  13:   
  14:          [MethodImpl(MethodImplOptions.NoInlining)]
  15:          private static ILog GetLog()
  16:          {
  17:              return IoC.Resolve<ILog>();
  18:          }
  19:   
  20:          [MethodImpl(MethodImplOptions.NoInlining)]
  21:          private static string Format(string format, params object[] args)
  22:          {
  23:              Check.Argument.IsNotEmpty(format, "format");
  24:   
  25:              return format.FormatWith(args);
  26:          }
  27:      }

未完、待续……

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏拂晓风起

事件响应的优先级、stopProgapation禁止下层组件响应

902
来自专栏.NET开发者社区

一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](四)

上一篇《一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](三)》,我们完成了:

2049
来自专栏大内老A

我的WCF之旅 (11): 再谈WCF的双向通讯-基于Http的双向通讯 V.S. 基于TCP的双向通讯

在一个基于面向服务的分布式环境中,借助一个标准的、平台无关的Communication Infrastructure,各个Service通过SOAP Messa...

2105
来自专栏熊二哥

快速入门系列--WCF--03RESTFUL服务与示例

之前介绍了基于SOAP的Web服务,接下来将介绍基于REST的轻量级的Web服务。 ? REST(Representational State Transfe...

1997
来自专栏大内老A

我的WCF之旅(2):Endpoint Overview

WCF实际上是构建了一个框架,这个框架实现了在互联系统中各个Application之间如何通信。使得Developers和Architect在构建分布式系统中,...

1967
来自专栏LanceToBigData

HttpClient(二)HttpClient使用Ip代理与处理连接超时

前言   其实前面写的那一点点东西都是轻轻点水,其实HttpClient还有很多强大的功能:   (1)实现了所有 HTTP 的方法(GET,POST,PUT,...

3358
来自专栏有困难要上,没有困难创造困难也要上!

在VirtualBox上使用Bosh部署Cloud Foundry

3507
来自专栏逸鹏说道

EF批量操作数据与缓存扩展框架

在原生的EF框架中,针对批量数据操作的接口有限,EF扩展框架弥补了EF在批量操作时的接口,这些批量操作包括:批量修改、批量查询、批量删除和数据缓存,如果您想在E...

3686
来自专栏hbbliyong

C#读取“我的文档”等特殊系统路径及环境变量

返回“我的文档”路径字符串 Environment.GetFolderPath(Environment.SpecialFolder.Personal) ? 本技...

3758
来自专栏Porschev[钟慰]的专栏

C# AD(Active Directory)域信息同步,组织单位、用户等信息查询

接上篇 Windows Server 2008 R2 配置AD(Active Directory)域控制器 对AD域结合常见需求用C#进行一些读取信息的操作...

3725

扫码关注云+社区