这几天利用空闲时间,我将ASP.NET反编译后的源代码并结合园子里几位大侠的写的文章认真的看了一遍,收获颇丰,同时也摘要了一些学习内容,存入了该篇文章:《ASP.NET运行机制图解》,在对整个ASP.NET的运行机制有所了解后,我又对MVC的运行机制也进行了源码分析,因为网上已经有很多的关于MVC实现原理的介绍,所以我这里不再重复讨论这方面的内容,而主要讲解一下Controller的的创建、执行以及如何实现依赖注入,注入的步骤是什么?

首先,我们来看一下正常的Controller的的创建与执行顺序:

大家都应该知道,用于处理ASP.NET请求是由实现了IHttpHandler的对象来进行处理的,我们所常见的Handler包括但不限于:Page,MvcHandler等

如下是MvcHandler类中的方法及执行步骤说明:

处理入口方法:异步-->BeginProcessRequest,同步-->  ProcessRequest,源代码如下:

        IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
return this.BeginProcessRequest(context, cb, extraData);
} void IHttpHandler.ProcessRequest(HttpContext httpContext)
{
this.ProcessRequest(httpContext);
}

注意这两个方法是显示实现IHttpHandler的同名方法的,不能直接调用,必需转换成IHttpHandler类型后才能调用,调用转到如下方法:

        protected virtual IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state)
{
HttpContextBase httpContext2 = new HttpContextWrapper(httpContext);
return this.BeginProcessRequest(httpContext2, callback, state);
} protected virtual void ProcessRequest(HttpContext httpContext)
{
HttpContextBase httpContext2 = new HttpContextWrapper(httpContext);
this.ProcessRequest(httpContext2);
}

当然这两个方法均又分别调动了各自的重载方法,在重载方法中都调用了ProcessRequestInit,源代码如下:

        private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
if (ValidationUtility.IsValidationEnabled(HttpContext.Current) == true)
{
ValidationUtility.EnableDynamicValidation(HttpContext.Current);
}
this.AddVersionHeader(httpContext);
this.RemoveOptionalRoutingParameters();
string requiredString = this.RequestContext.RouteData.GetRequiredString("controller");
factory = this.ControllerBuilder.GetControllerFactory();
controller = factory.CreateController(this.RequestContext, requiredString);
if (controller == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.ControllerBuilder_FactoryReturnedNull, new object[]
{
factory.GetType(),
requiredString
}));
}
}

红色标明的就是创建Controller的地方,创建完后就开始执行Controller,异步与同步方法的执行有所不同,源代码如下:

        protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)
{
return SecurityUtil.ProcessInApplicationTrust<IAsyncResult>(delegate
{
IController controller;
IControllerFactory factory;
this.ProcessRequestInit(httpContext, out controller, out factory);
IAsyncController asyncController = controller as IAsyncController;
if (asyncController != null)
{
BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState)
{
IAsyncResult result;
try
{
result = asyncController.BeginExecute(this.RequestContext, asyncCallback, asyncState);
}
catch
{
factory.ReleaseController(asyncController);
throw;
}
return result;
};
EndInvokeDelegate endDelegate = delegate(IAsyncResult asyncResult)
{
try
{
asyncController.EndExecute(asyncResult);
}
finally
{
factory.ReleaseController(asyncController);
}
};
SynchronizationContext synchronizationContext = SynchronizationContextUtil.GetSynchronizationContext();
AsyncCallback callback2 = AsyncUtil.WrapCallbackForSynchronizedExecution(callback, synchronizationContext);
return AsyncResultWrapper.Begin(callback2, state, beginDelegate, endDelegate, MvcHandler._processRequestTag);
}
Action action = delegate
{
try
{
controller.Execute(this.RequestContext);
}
finally
{
factory.ReleaseController(controller);
}
};
return AsyncResultWrapper.BeginSynchronous(callback, state, action, MvcHandler._processRequestTag);
});
} protected internal virtual void EndProcessRequest(IAsyncResult asyncResult)
{
SecurityUtil.ProcessInApplicationTrust(delegate
{
AsyncResultWrapper.End(asyncResult, MvcHandler._processRequestTag);
});
} protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
SecurityUtil.ProcessInApplicationTrust(delegate
{
IController controller;
IControllerFactory controllerFactory;
this.ProcessRequestInit(httpContext, out controller, out controllerFactory);
try
{
controller.Execute(this.RequestContext);
}
finally
{
controllerFactory.ReleaseController(controller);
}
});
}

通过上述代码,我们知道Controller执行步骤是:异步(BeginExecute-->EndExecute-->ReleaseController),同步(Execute-->  ReleaseController)

我们知道了Controller的创建与执行原理,就可以针对这些代码规则来扩展我们自定义的一些实现代码,比如我们本文要讲的:通过IOC实现Controller依赖注入。

通过上面源代码的分析,我们知道,Controller是由ControllerFactory来创建的,而ControllerFactory又是由ControllerBuilder,也就是我们只要能够改变ControllerBuilder.GetControllerFactory返回的值,也就改变了ControllerFactory,这样就给自定义创建Controller提供可能,我们先来看一下,ControllerBuilder.GetControllerFactory方法的定义:

public IControllerFactory GetControllerFactory()
{
return this._serviceResolver.Current;
}

方法很简单,直接通过IResolver<IControllerFactory>.Current返回实现了IControllerFactory对象,而对于方法中的_serviceResolver是在构造函数中实例化的,源代码如下:

        internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver)
{
IResolver<IControllerFactory> arg_6A_1 = serviceResolver;
if (serviceResolver == null)
{
arg_6A_1 = new SingleServiceResolver<IControllerFactory>(() => this._factoryThunk(), new DefaultControllerFactory
{
ControllerBuilder = this
}, "ControllerBuilder.GetControllerFactory"
);
}
this._serviceResolver = arg_6A_1;
}

通过构造函数,可以看出_serviceResolver是由SingleServiceResolver<IControllerFactory>实例化得来的,那么结合上面的this._serviceResolver.Current,就可以知道其实就是访问SingleServiceResolver<IControllerFactory>的Current属性来获得IControllerFactory对象,源代码如下:

        public TService Current
{
get
{
if (this._resolverThunk != null)
{
lock (this._currentValueThunk)
{
if (this._resolverThunk != null)
{
this._currentValueFromResolver = this._resolverThunk().GetService<TService>();
this._resolverThunk = null;
if (this._currentValueFromResolver != null && this._currentValueThunk() != null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.SingleServiceResolver_CannotRegisterTwoInstances, new object[]
{
typeof(TService).Name.ToString(),
this._callerMethodName
}));
}
}
}
}
TService arg_D2_0;
if ((arg_D2_0 = this._currentValueFromResolver) == null && (arg_D2_0 = this._currentValueThunk()) == null)
{
arg_D2_0 = this._defaultValue;
}
return arg_D2_0;
}
}

SingleServiceResolver构造函数如下:

        public SingleServiceResolver(Func<TService> currentValueThunk, TService defaultValue, string callerMethodName)
{
if (currentValueThunk == null)
{
throw new ArgumentNullException("currentValueThunk");
}
if (defaultValue == null)
{
throw new ArgumentNullException("defaultValue");
}
this._resolverThunk = (() => DependencyResolver.Current);
this._currentValueThunk = currentValueThunk;
this._defaultValue = defaultValue;
this._callerMethodName =
callerMethodName;
}

这里我们结合ControllerBuilder的构造函数及SingleServiceResolver构造函数得知在Current属性的逻辑代码中if (this._currentValueFromResolver != null && this._currentValueThunk() != null)是不成立的,因为this._currentValueThunk = currentValueThunk;而currentValueThunk又是ControllerBuilder中默认的值: Func<IControllerFactory> _factoryThunk = () => null;所以就会走到arg_D2_0 = this._defaultValue,而_defaultValue又是等于ControllerBuilder构造函数中传来的DefaultControllerFactory,所以最终返回了DefaultControllerFactory,如果需要实现自定义的ControllerFactory并且能够被ControllerBuilder.GetControllerFactory返回,我们只需要自定义实现IControllerFactory的类,如:CustomControllerFactory,以及使用ControllerBuilder.SetControllerFactory方法来使_factoryThunk 的值等于()=>CustomControllerFactory即可,实现的代码如下:

    public class CustomControllerFactory : DefaultControllerFactory
{
private UnityContainer iocContainer; public CustomControllerFactory()
{
iocContainer = new UnityContainer();
AddBindings();
} protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
IController controller=null;
if (controllerType != null)
{
controller = (IController)iocContainer.Resolve(controllerType);
}
return controller;
} private void AddBindings()
{
iocContainer.RegisterType<IUserService, UserService>();
} }

我这里采用Unity容器,并重写了GetControllerInstance方法,如下代码是实现注入CustomControllerFactory到ControllerBuilder:

        protected void Application_Start()
{
AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes); ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());
}

这样我们就实现了返回自己定义的CustomControllerFactory,并在CustomControllerFactory通过IOC容器来实现自己所需要的Controller。

以上虽然通过自定义ControllerFactory实现了IOC的注入,但我仍然觉得有些烦锁,且存在不安全性,因为自己实现的CustomControllerFactory是可以去重写、覆盖改变DefaultControllerFactory中的相应的属性方法,如果自己写的代码存在漏洞或不健全,则会造成无法预料的后果,因此一般不建议直接这样做,而应该采用风险更小的其它方法来实现,那是什么方法呢?请继续往下看。

通过分析源码得知,默认情况下,Controller是由DefaultControllerFactory.GetControllerInstance得来的,那我们先来看看这个方法定义:

        protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(, string.Format(CultureInfo.CurrentCulture, MvcResources.DefaultControllerFactory_NoControllerFound, new object[]
{
requestContext.HttpContext.Request.Path
}));
}
if (!typeof(IController).IsAssignableFrom(controllerType))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, MvcResources.DefaultControllerFactory_TypeDoesNotSubclassControllerBase, new object[]
{
controllerType
}), "controllerType");
}
return this.ControllerActivator.Create(requestContext, controllerType);
}

注意红色标注的地方,这里是通过ControllerActivator属性对象来创建的,ControllerActivator属性定义如下:

        private IControllerActivator ControllerActivator
{
get
{
if (this._controllerActivator != null)
{
return this._controllerActivator;
}
this._controllerActivator = this._activatorResolver.Current;
return this._controllerActivator;
}
}

由此可知,ControllerActivator属性又是(私有字段:_activatorResolver) IResolver<IControllerActivator>.Current得来的,那么这个_activatorResolver又是如何得来的呢?通过上下源码的分析,得知,DefaultControllerFactory是在ControllerBuilder中构造的,那么我看一下DefaultControllerFactory的构造函数:

        public DefaultControllerFactory() : this(null, null, null)
{
} internal DefaultControllerFactory(IControllerActivator controllerActivator, IResolver<IControllerActivator> activatorResolver, IDependencyResolver dependencyResolver)
{
if (controllerActivator != null)
{
this._controllerActivator = controllerActivator;
return;
}
IResolver<IControllerActivator> arg_44_1 = activatorResolver;
if (activatorResolver == null)
{
arg_44_1 = new SingleServiceResolver<IControllerActivator>(() => null, new DefaultControllerFactory.DefaultControllerActivator(dependencyResolver), "DefaultControllerFactory contstructor");
}
this._activatorResolver = arg_44_1;
}

ControllerBuilder的构造函数中是采用的无参构造函数,而无参构造函数最终均会调用带有三个参数的构造函数,在这个函数中,我标出了重点需要关注的地方,有没有发现眼熟的地方,对的SingleServiceResolver又出现了,只不过泛型参数不同而已,我在上面分析时用绿色标记出了重要的地方:构造函数中的this._resolverThunk = (() => DependencyResolver.Current);以及Current属性中的this._currentValueFromResolver = this._resolverThunk().GetService<TService>();认真分析得知, DependencyResolver.Current是一个静态属性,看一下该属性的定义:

public static IDependencyResolver Current
{
get
{
return DependencyResolver._instance.InnerCurrent;
}
}

该属性的值来源于一个私有字段,这个字段是静态的并默认就实例化为DependencyResolver:

private static DependencyResolver _instance = new DependencyResolver();

得出结论DependencyResolver.Current调用DependencyResolver.InnerCurrent属性,而该属性又直接返回_current字段的值,代码如下:

private IDependencyResolver _current = new DependencyResolver.DefaultDependencyResolver();

        public IDependencyResolver InnerCurrent
{
get
{
return this._current;
}
}

_current字段默认是实例化DependencyResolver.DefaultDependencyResolver,而该类型是一个内部类:

        private class DefaultDependencyResolver : IDependencyResolver
{
public object GetService(Type serviceType)
{
object result;
try
{
result = Activator.CreateInstance(serviceType);
}
catch
{
result = null;
}
return result;
} public IEnumerable<object> GetServices(Type serviceType)
{
return Enumerable.Empty<object>();
}
}

这个类没有什么复杂的方法及属性,只是实现了IDependencyResolver接口的两个方法,分别是  GetService、  GetServices(该方法返回空集合,即无用)。

到此一切就都明了了,如果说想要实现通过DefaultControllerFactory.GetControllerInstance来返回我们IOC注入后的Controller,只需要改变  SingleServiceResolver.Current属性返回值,而改变该值则需要改变该类的_resolverThunk字段值,而_resolverThunk的值又来自构造函数中的如下语句:

this._resolverThunk = (() => DependencyResolver.Current);

最终我们只要改变DependencyResolver.Current属性返回值即可,而该值通过上面的分析知道是来自DependencyResolver的字段:_current,所以只要改变这个字段的值,就能改变最终返回Controller实例对象。那如何改变这个私有字段呢?不急,通过源码代码得知,DependencyResolver提供了SetResolver多个静态重载方法,我们只需要将实现了IDependencyResolver接口实例对象传入进去,就可以改变_current字段,从而最终实现我们想要的结果。

        public static void SetResolver(IDependencyResolver resolver)
{
DependencyResolver._instance.InnerSetResolver(resolver);
} public static void SetResolver(object commonServiceLocator)
{
DependencyResolver._instance.InnerSetResolver(commonServiceLocator);
} public static void SetResolver(Func<Type, object> getService, Func<Type, IEnumerable<object>> getServices)
{
DependencyResolver._instance.InnerSetResolver(getService, getServices);
} public void InnerSetResolver(IDependencyResolver resolver)
{
if (resolver == null)
{
throw new ArgumentNullException("resolver");
}
this._current = resolver;
} public void InnerSetResolver(object commonServiceLocator)
{
if (commonServiceLocator == null)
{
throw new ArgumentNullException("commonServiceLocator");
}
Type type = commonServiceLocator.GetType();
MethodInfo method = type.GetMethod("GetInstance", new Type[]
{
typeof(Type)
});
MethodInfo method2 = type.GetMethod("GetAllInstances", new Type[]
{
typeof(Type)
});
if (method == null || method.ReturnType != typeof(object) || method2 == null || method2.ReturnType != typeof(IEnumerable<object>))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, MvcResources.DependencyResolver_DoesNotImplementICommonServiceLocator, new object[]
{
type.FullName
}), "commonServiceLocator");
}
Func<Type, object> getService = (Func<Type, object>)Delegate.CreateDelegate(typeof(Func<Type, object>), commonServiceLocator, method);
Func<Type, IEnumerable<object>> getServices = (Func<Type, IEnumerable<object>>)Delegate.CreateDelegate(typeof(Func<Type, IEnumerable<object>>), commonServiceLocator, method2);
this._current = new DependencyResolver.DelegateBasedDependencyResolver(getService, getServices);
} public void InnerSetResolver(Func<Type, object> getService, Func<Type, IEnumerable<object>> getServices)
{
if (getService == null)
{
throw new ArgumentNullException("getService");
}
if (getServices == null)
{
throw new ArgumentNullException("getServices");
}
this._current = new DependencyResolver.DelegateBasedDependencyResolver(getService, getServices);
}

自定义实现IDependencyResolver接口的类型(采用Unity需要注意,使用常规的解析方法会存在错误,可参见DUDU的这篇文章《Unity+MVC:实现IDependencyResolver接口需要注意的地方》,我这里直接借鉴Unity.MVC3里面定义的类),如:

    public class CustomDependencyResolver:IDependencyResolver
{
private const string HttpContextKey = "perRequestContainer"; private readonly IUnityContainer container; public CustomDependencyResolver()
{
this.container = BuildAndInitContainer();
} public object GetService(Type serviceType)
{
if (typeof(IController).IsAssignableFrom(serviceType))
{
return ChildContainer.Resolve(serviceType);
} return IsRegistered(serviceType) ? ChildContainer.Resolve(serviceType) : null;
} public IEnumerable<object> GetServices(Type serviceType)
{
if (IsRegistered(serviceType))
{
yield return ChildContainer.Resolve(serviceType);
} foreach (var service in ChildContainer.ResolveAll(serviceType))
{
yield return service;
}
} protected IUnityContainer ChildContainer
{
get
{
var childContainer = HttpContext.Current.Items[HttpContextKey] as IUnityContainer; if (childContainer == null)
{
HttpContext.Current.Items[HttpContextKey] = childContainer = container.CreateChildContainer();
} return childContainer;
}
} public static void DisposeOfChildContainer()
{
var childContainer = HttpContext.Current.Items[HttpContextKey] as IUnityContainer; if (childContainer != null)
{
childContainer.Dispose();
}
} private bool IsRegistered(Type typeToCheck)
{
var isRegistered = true; if (typeToCheck.IsInterface || typeToCheck.IsAbstract)
{
isRegistered = ChildContainer.IsRegistered(typeToCheck); if (!isRegistered && typeToCheck.IsGenericType)
{
var openGenericType = typeToCheck.GetGenericTypeDefinition(); isRegistered = ChildContainer.IsRegistered(openGenericType);
}
} return isRegistered;
} private IUnityContainer BuildAndInitContainer()
{
var container = new UnityContainer(); container.RegisterType<IUserService, UserService>();
//这里添加其它类型映射 return container;
}
}

在Global文件的Application_Start方法中添加注入代码,如下:

        protected void Application_Start()
{
AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes); DependencyResolver.SetResolver(new MvcApplication1.Models.CustomDependencyResolver());
}

使用方法很简单,如下是全部代码:

    public interface IUserService
{
bool Login(string userName, string password, out string failureMsg);
} public class UserService : IUserService
{
public bool Login(string userName, string password, out string failureMsg)
{
failureMsg = null;
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
{
failureMsg = "用户名或密码不能为空!";
return false;
} if (userName != "admin" || password != "web.admin")
{
failureMsg = "用户名或密码不正确!";
return false;
} return true;
}
} public class UserController : Controller
{
private readonly IUserService userService; public UserController(IUserService service)
{
userService = service;
} public ActionResult Login()
{
return View();
} [HttpPost]
[ActionName("Login")]
public ActionResult LoginExecute(string username, string password)
{
string msg = null;
if (!userService.Login(username, password,out msg))
{
return Content("<p style='color:red;'>登录失败,原因如下:<br/>"+ msg +"</p>", "text/html", Encoding.UTF8);
}
return Content("<p style='color:green;'>登录成功!</p>", "text/html", Encoding.UTF8);
} }

VIEW视图代码:

@{
ViewBag.Title = "Login";
} <h2>Login</h2> @using(Html.BeginForm())
{
<p>
<span>用户名:</span>
@Html.TextBox("username")
</p>
<p>
<span>密 码:</span>
@Html.Password("password")
</p>
<input type="submit" value="登 录" />
}

最终的效果如下图示:

                        

                        

深入分析MVC中通过IOC实现Controller依赖注入的原理的更多相关文章

  1. AspectCore中的IoC容器和依赖注入

    IOC模式和依赖注入是近年来非常流行的一种模式,相信大家都不陌生了,在Asp.Net Core中提供了依赖注入作为内置的基础设施,如果仍不熟悉依赖注入的读者,可以看看由我们翻译的Asp.Net Cor ...

  2. ASP.NET MVC进阶之路:深入理解依赖注入(DI)和控制反转(IOC)

    0X1 什么是依赖注入 依赖注入(Dependency Injection),是这样一个过程:某客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户类只定义一个注入点.在程序运行过程中,客户 ...

  3. ASP.NET MVC和ASP.NET Core MVC中获取当前URL/Controller/Action (转载)

    ASP.NET MVC 一.获取URL(ASP.NET通用): [1]获取完整url(协议名+域名+虚拟目录名+文件名+参数) string url=Request.Url.ToString(); [ ...

  4. 轻松了解Spring中的控制反转和依赖注入(二)

    紧接上一篇文章<轻松了解Spring中的控制反转和依赖注入>讲解了SpringIOC和DI的基本概念,这篇文章我们模拟一下SpringIOC的工作机制,使我们更加深刻的理解其中的工作. 类 ...

  5. 控制反转(IoC)与依赖注入(DI)

    前言 最近在学习Spring框架,它的核心就是IoC容器.要掌握Spring框架,就必须要理解控制反转的思想以及依赖注入的实现方式.下面,我们将围绕下面几个问题来探讨控制反转与依赖注入的关系以及在Sp ...

  6. IOC容器的依赖注入

    1.依赖注入发生的时间 当Spring IoC容器完成了Bean定义资源的定位.载入和解析注册以后,IoC容器中已经管理类Bean定义的相关数据,但是此时IoC容器还没有对所管理的Bean进行依赖注入 ...

  7. 控制反转( IoC)和依赖注入(DI)

    控制反转( IoC)和依赖注入(DI) tags: 容器 依赖注入 IOC DI 控制反转 引言:如果你看过一些框架的源码或者手册,像是laravel或者tp5之类的,应该会提到容器,依赖注入,控制反 ...

  8. Spring IOC - 控制反转(依赖注入) - 入门案例 - 获取对象的方式 - 别名标签

    1. IOC - 控制反转(依赖注入) 所谓的IOC称之为控制反转,简单来说就是将对象的创建的权利及对象的生命周期的管理过程交 由Spring框架来处理,从此在开发过程中不再需要关注对象的创建和生命周 ...

  9. springboot成神之——ioc容器(依赖注入)

    springboot成神之--ioc容器(依赖注入) spring的ioc功能 文件目录结构 lang Chinese English GreetingService MyRepository MyC ...

随机推荐

  1. SQL入门经典(二) 之数据库基本查询、添加、更新和删除

    使用SQL查询: SQL查询基本语法: SELECT [ALL|DISTINCT]  [TOP (<expression>) [PERCENT] [WITH TIES] ] <col ...

  2. 字符串反混淆实战 Dotfuscator 4.9 字符串加密技术应对策略

    因为手头需要使用一个第三方类库,网络上又找不到它的可用的版本,于是只好自己动手.这个类库使用了Dotfuscator 加密,用.NET Reflector加载程序集, 看到的字符串是乱码,如下面的代码 ...

  3. Building Apps for Windows Phone 8.1教程下载地址整理

    官方教程地址http://channel9.msdn.com/Series/Building-Apps-for-Windows-Phone-8-1http://media.ch9.ms/ch9/8db ...

  4. Yii2中的零碎知识点

    PHP最佳实践 1 PHP获取时间戳:echo  time(); 时间戳转换 date('Y-m-d H:i:s', $时间戳); 2 linux 显示命令 ls 显示所有文件夹 查看命令:tail ...

  5. objective-c(代码块)

    objective-c代码块(block)对写惯C语言的人非常熟悉,就类似一个函数指针,指向一个代码段的首地址: 给出简单例子如下: int main(int argc, const char * a ...

  6. UWP中的Direct2D

    介绍 DirectX一直是Windows平台中高性能图形的代名词,自Win7开始,微软又推出了Direct2D技术,包装于Direct3D,但专注于2D图形,并且准备取代GDI这样的传统2D图形技术. ...

  7. Windows Phone 8.1上的开发人员请看

    1)SDK选择:如果你是在Windows Phone 8.1上做一个新App, 或者想把7.x/8.0的App移植到8.1上,请使用WinRT SDK,而不是Silverlight.当然Silverl ...

  8. Android消息机制

    每一个Android应用在启动的时候都会创建一个线程,这个线程被称为主线程或者UI线程,Android应用的所有操作默认都会运行在这个线程中. 但是当我们想要进行数据请求,图片下载,或者其他耗时操作时 ...

  9. 自己封装个ajax

    你是否发现项目中有很多页面只用到了框架不到十分之一的内容,还引了压缩后还有70多kb的jquery库 你是否发现项目中就用了两三个underscore提供的方法,其他大部分的你方法你甚至从来没有看过 ...

  10. 黑马程序员_java08_多线程

    转载于:http://www.itxuexiwang.com/plus/view.php?aid=148 线程是程序中可以并行执行的任务. java运行系统总是选当前优先级最高的处于就绪状态的线程来执 ...