一、基础介绍

依赖注入,Dependency Injection,权威解释及说明请自己查阅资料。
这里简单说一下常见使用:在mvc的controller的构造方法中定义参数,如ICountryService countryService,然后直接使用countryService(构造注入)。
         public CountryController(ICountryService countryService,
IStateProvinceService stateProvinceService,
ILocalizationService localizationService,
IWorkContext workContext,
ICacheManager cacheManager)
{
this._countryService = countryService;
this._stateProvinceService = stateProvinceService;
this._localizationService = localizationService;
this._workContext = workContext;
this._cacheManager = cacheManager;
}

显然,你并没有在controller调用前,new一个ICountryService的对象给controller做参数,你也不知道该在哪去写这个调用。没关系,这些都交给系统处理,你不必理会,这就是依赖注入。

二、承上启下

上一篇大致分析了应用启动,而NopCommerce完成注册依赖就在初始化上下文部分。通过代码跟踪,即可发现Nop.Core.Infrastructure.NopEngine.RegisterDependencies()。

             //initialize engine context 初始化上下文
EngineContext.Initialize(false);
         /// <summary>
/// Initializes a static instance of the Nop factory.
/// </summary>
/// <param name="forceRecreate">Creates a new factory instance even though the factory has been previously initialized.</param>
[MethodImpl(MethodImplOptions.Synchronized)]
public static IEngine Initialize(bool forceRecreate)
{
if (Singleton<IEngine>.Instance == null || forceRecreate)
{
Singleton<IEngine>.Instance = new NopEngine(); var config = ConfigurationManager.GetSection("NopConfig") as NopConfig;
Singleton<IEngine>.Instance.Initialize(config);
}
return Singleton<IEngine>.Instance;
}
         /// <summary>
/// Initialize components and plugins in the nop environment.
/// </summary>
/// <param name="config">Config</param>
public void Initialize(NopConfig config)
{
//register dependencies
RegisterDependencies(config); //startup tasks
if (!config.IgnoreStartupTasks)
{
RunStartupTasks();
} }
         /// <summary>
/// Register dependencies
/// </summary>
/// <param name="config">Config</param>
protected virtual void RegisterDependencies(NopConfig config)
{
var builder = new ContainerBuilder();
var container = builder.Build();
this._containerManager = new ContainerManager(container); //we create new instance of ContainerBuilder
//because Build() or Update() method can only be called once on a ContainerBuilder. //dependencies
var typeFinder = new WebAppTypeFinder();
builder = new ContainerBuilder();
builder.RegisterInstance(config).As<NopConfig>().SingleInstance();
builder.RegisterInstance(this).As<IEngine>().SingleInstance();
builder.RegisterInstance(typeFinder).As<ITypeFinder>().SingleInstance();
builder.Update(container); //register dependencies provided by other assemblies
builder = new ContainerBuilder();
var drTypes = typeFinder.FindClassesOfType<IDependencyRegistrar>();
var drInstances = new List<IDependencyRegistrar>();
foreach (var drType in drTypes)
drInstances.Add((IDependencyRegistrar) Activator.CreateInstance(drType));
//sort
drInstances = drInstances.AsQueryable().OrderBy(t => t.Order).ToList();
foreach (var dependencyRegistrar in drInstances)
dependencyRegistrar.Register(builder, typeFinder, config);通过反射,按顺序注册依赖
builder.Update(container); //set dependency resolver
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}

三、NopCommerce的结构分析

  本文通过从依赖注入框架Autofac的DependencyRegistrar方法来分析NopCommerce的结构。

1.分析方法

  在vs里Solution Explorer的查找栏输入DependencyRegistrar,即可看到所有实现DependencyRegistrar()方法的。

  2.总结

    2.1 Nop.Core定义了接口;

    2.2 Plugins注册自己需要的类;

    2.3 Nop.Admin和Nop.Web注册Controller所要使用的缓存类;

    2.4 Nop.Web.Framework注册了NopCommerce的核心类。

四、代码分析

  1.这里主要分析Nop.Web.Framework的DependencyRegistrar()

  1.1.注册http上下文;

  1.2.注册web helper、user agent helper;

  1.3.注册mvc的controllers;

  1.4.注册数据层类,如dbcontext,manager,repository,供持久化层的操作;

  1.5.注册插件plugins;

  1.6.注册缓存管理的相关类;

  1.7.注册work context和store context;

  1.8.注册业务层services,部分需注册缓存参数,可以看到WithParameter( ResolvedParameter.ForNamed< ICacheManager >("nop_cache_static" ));

  1.9.注册用户事件。

2.代码如下

         /// <summary>
/// Register services and interfaces
/// </summary>
/// <param name="builder">Container builder</param>
/// <param name="typeFinder">Type finder</param>
/// <param name="config">Config</param>
public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config)
{
//HTTP context and other related stuff
builder.Register(c =>
//register FakeHttpContext when HttpContext is not available
HttpContext.Current != null ?
(new HttpContextWrapper(HttpContext.Current) as HttpContextBase) :
(new FakeHttpContext("~/") as HttpContextBase))
.As<HttpContextBase>()
.InstancePerLifetimeScope();
builder.Register(c => c.Resolve<HttpContextBase>().Request)
.As<HttpRequestBase>()
.InstancePerLifetimeScope();
builder.Register(c => c.Resolve<HttpContextBase>().Response)
.As<HttpResponseBase>()
.InstancePerLifetimeScope();
builder.Register(c => c.Resolve<HttpContextBase>().Server)
.As<HttpServerUtilityBase>()
.InstancePerLifetimeScope();
builder.Register(c => c.Resolve<HttpContextBase>().Session)
.As<HttpSessionStateBase>()
.InstancePerLifetimeScope(); //web helper
builder.RegisterType<WebHelper>().As<IWebHelper>().InstancePerLifetimeScope();
//user agent helper
builder.RegisterType<UserAgentHelper>().As<IUserAgentHelper>().InstancePerLifetimeScope(); //controllers
builder.RegisterControllers(typeFinder.GetAssemblies().ToArray()); //data layer
var dataSettingsManager = new DataSettingsManager();
var dataProviderSettings = dataSettingsManager.LoadSettings();
builder.Register(c => dataSettingsManager.LoadSettings()).As<DataSettings>();
builder.Register(x => new EfDataProviderManager(x.Resolve<DataSettings>())).As<BaseDataProviderManager>().InstancePerDependency(); builder.Register(x => x.Resolve<BaseDataProviderManager>().LoadDataProvider()).As<IDataProvider>().InstancePerDependency(); if (dataProviderSettings != null && dataProviderSettings.IsValid())
{
var efDataProviderManager = new EfDataProviderManager(dataSettingsManager.LoadSettings());
var dataProvider = efDataProviderManager.LoadDataProvider();
dataProvider.InitConnectionFactory(); builder.Register<IDbContext>(c => new NopObjectContext(dataProviderSettings.DataConnectionString)).InstancePerLifetimeScope();
}
else
{
builder.Register<IDbContext>(c => new NopObjectContext(dataSettingsManager.LoadSettings().DataConnectionString)).InstancePerLifetimeScope();
} builder.RegisterGeneric(typeof(EfRepository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope(); //plugins
builder.RegisterType<PluginFinder>().As<IPluginFinder>().InstancePerLifetimeScope();
builder.RegisterType<OfficialFeedManager>().As<IOfficialFeedManager>().InstancePerLifetimeScope(); //cache managers
if (config.RedisCachingEnabled)
{
builder.RegisterType<RedisCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_static").InstancePerLifetimeScope();
}
else
{
builder.RegisterType<MemoryCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_static").SingleInstance();
}
builder.RegisterType<PerRequestCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_per_request").InstancePerLifetimeScope(); if (config.RunOnAzureWebsites)
{
builder.RegisterType<AzureWebsitesMachineNameProvider>().As<IMachineNameProvider>().SingleInstance();
}
else
{
builder.RegisterType<DefaultMachineNameProvider>().As<IMachineNameProvider>().SingleInstance();
} //work context
builder.RegisterType<WebWorkContext>().As<IWorkContext>().InstancePerLifetimeScope();
//store context
builder.RegisterType<WebStoreContext>().As<IStoreContext>().InstancePerLifetimeScope(); //services
builder.RegisterType<BackInStockSubscriptionService>().As<IBackInStockSubscriptionService>().InstancePerLifetimeScope();
builder.RegisterType<CategoryService>().As<ICategoryService>().InstancePerLifetimeScope();
builder.RegisterType<CompareProductsService>().As<ICompareProductsService>().InstancePerLifetimeScope();
builder.RegisterType<RecentlyViewedProductsService>().As<IRecentlyViewedProductsService>().InstancePerLifetimeScope();
builder.RegisterType<ManufacturerService>().As<IManufacturerService>().InstancePerLifetimeScope();
builder.RegisterType<PriceFormatter>().As<IPriceFormatter>().InstancePerLifetimeScope();
builder.RegisterType<ProductAttributeFormatter>().As<IProductAttributeFormatter>().InstancePerLifetimeScope();
builder.RegisterType<ProductAttributeParser>().As<IProductAttributeParser>().InstancePerLifetimeScope();
builder.RegisterType<ProductAttributeService>().As<IProductAttributeService>().InstancePerLifetimeScope();
builder.RegisterType<ProductService>().As<IProductService>().InstancePerLifetimeScope();
builder.RegisterType<CopyProductService>().As<ICopyProductService>().InstancePerLifetimeScope();
builder.RegisterType<SpecificationAttributeService>().As<ISpecificationAttributeService>().InstancePerLifetimeScope();
builder.RegisterType<ProductTemplateService>().As<IProductTemplateService>().InstancePerLifetimeScope();
builder.RegisterType<CategoryTemplateService>().As<ICategoryTemplateService>().InstancePerLifetimeScope();
builder.RegisterType<ManufacturerTemplateService>().As<IManufacturerTemplateService>().InstancePerLifetimeScope();
builder.RegisterType<TopicTemplateService>().As<ITopicTemplateService>().InstancePerLifetimeScope();
//use static cache (between HTTP requests)
builder.RegisterType<ProductTagService>().As<IProductTagService>()
.WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
.InstancePerLifetimeScope(); builder.RegisterType<AddressAttributeFormatter>().As<IAddressAttributeFormatter>().InstancePerLifetimeScope();
builder.RegisterType<AddressAttributeParser>().As<IAddressAttributeParser>().InstancePerLifetimeScope();
builder.RegisterType<AddressAttributeService>().As<IAddressAttributeService>().InstancePerLifetimeScope();
builder.RegisterType<AddressService>().As<IAddressService>().InstancePerLifetimeScope();
builder.RegisterType<AffiliateService>().As<IAffiliateService>().InstancePerLifetimeScope();
builder.RegisterType<VendorService>().As<IVendorService>().InstancePerLifetimeScope();
builder.RegisterType<SearchTermService>().As<ISearchTermService>().InstancePerLifetimeScope();
builder.RegisterType<GenericAttributeService>().As<IGenericAttributeService>().InstancePerLifetimeScope();
builder.RegisterType<FulltextService>().As<IFulltextService>().InstancePerLifetimeScope();
builder.RegisterType<MaintenanceService>().As<IMaintenanceService>().InstancePerLifetimeScope(); builder.RegisterType<CustomerAttributeParser>().As<ICustomerAttributeParser>().InstancePerLifetimeScope();
builder.RegisterType<CustomerAttributeService>().As<ICustomerAttributeService>().InstancePerLifetimeScope();
builder.RegisterType<CustomerService>().As<ICustomerService>().InstancePerLifetimeScope();
builder.RegisterType<CustomerRegistrationService>().As<ICustomerRegistrationService>().InstancePerLifetimeScope();
builder.RegisterType<CustomerReportService>().As<ICustomerReportService>().InstancePerLifetimeScope(); //use static cache (between HTTP requests)
builder.RegisterType<PermissionService>().As<IPermissionService>()
.WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
.InstancePerLifetimeScope();
//use static cache (between HTTP requests)
builder.RegisterType<AclService>().As<IAclService>()
.WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
.InstancePerLifetimeScope();
//use static cache (between HTTP requests)
builder.RegisterType<PriceCalculationService>().As<IPriceCalculationService>()
.WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
.InstancePerLifetimeScope(); builder.RegisterType<GeoLookupService>().As<IGeoLookupService>().InstancePerLifetimeScope();
builder.RegisterType<CountryService>().As<ICountryService>().InstancePerLifetimeScope();
builder.RegisterType<CurrencyService>().As<ICurrencyService>().InstancePerLifetimeScope();
builder.RegisterType<MeasureService>().As<IMeasureService>().InstancePerLifetimeScope();
builder.RegisterType<StateProvinceService>().As<IStateProvinceService>().InstancePerLifetimeScope(); builder.RegisterType<StoreService>().As<IStoreService>().InstancePerLifetimeScope();
//use static cache (between HTTP requests)
builder.RegisterType<StoreMappingService>().As<IStoreMappingService>()
.WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
.InstancePerLifetimeScope(); builder.RegisterType<DiscountService>().As<IDiscountService>().InstancePerLifetimeScope(); //use static cache (between HTTP requests)
builder.RegisterType<SettingService>().As<ISettingService>()
.WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
.InstancePerLifetimeScope();
builder.RegisterSource(new SettingsSource()); //use static cache (between HTTP requests)
builder.RegisterType<LocalizationService>().As<ILocalizationService>()
.WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
.InstancePerLifetimeScope(); //use static cache (between HTTP requests)
builder.RegisterType<LocalizedEntityService>().As<ILocalizedEntityService>()
.WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
.InstancePerLifetimeScope();
builder.RegisterType<LanguageService>().As<ILanguageService>().InstancePerLifetimeScope(); builder.RegisterType<DownloadService>().As<IDownloadService>().InstancePerLifetimeScope();
//picture service
var useAzureBlobStorage = !String.IsNullOrEmpty(config.AzureBlobStorageConnectionString);
if (useAzureBlobStorage)
{
//Windows Azure BLOB
builder.RegisterType<AzurePictureService>().As<IPictureService>().InstancePerLifetimeScope();
}
else
{
//standard file system
builder.RegisterType<PictureService>().As<IPictureService>().InstancePerLifetimeScope();
} builder.RegisterType<MessageTemplateService>().As<IMessageTemplateService>().InstancePerLifetimeScope();
builder.RegisterType<QueuedEmailService>().As<IQueuedEmailService>().InstancePerLifetimeScope();
builder.RegisterType<NewsLetterSubscriptionService>().As<INewsLetterSubscriptionService>().InstancePerLifetimeScope();
builder.RegisterType<CampaignService>().As<ICampaignService>().InstancePerLifetimeScope();
builder.RegisterType<EmailAccountService>().As<IEmailAccountService>().InstancePerLifetimeScope();
builder.RegisterType<WorkflowMessageService>().As<IWorkflowMessageService>().InstancePerLifetimeScope();
builder.RegisterType<MessageTokenProvider>().As<IMessageTokenProvider>().InstancePerLifetimeScope();
builder.RegisterType<Tokenizer>().As<ITokenizer>().InstancePerLifetimeScope();
builder.RegisterType<EmailSender>().As<IEmailSender>().InstancePerLifetimeScope(); builder.RegisterType<CheckoutAttributeFormatter>().As<ICheckoutAttributeFormatter>().InstancePerLifetimeScope();
builder.RegisterType<CheckoutAttributeParser>().As<ICheckoutAttributeParser>().InstancePerLifetimeScope();
builder.RegisterType<CheckoutAttributeService>().As<ICheckoutAttributeService>().InstancePerLifetimeScope();
builder.RegisterType<GiftCardService>().As<IGiftCardService>().InstancePerLifetimeScope();
builder.RegisterType<OrderService>().As<IOrderService>().InstancePerLifetimeScope();
builder.RegisterType<OrderReportService>().As<IOrderReportService>().InstancePerLifetimeScope();
builder.RegisterType<OrderProcessingService>().As<IOrderProcessingService>().InstancePerLifetimeScope();
builder.RegisterType<OrderTotalCalculationService>().As<IOrderTotalCalculationService>().InstancePerLifetimeScope();
builder.RegisterType<ReturnRequestService>().As<IReturnRequestService>().InstancePerLifetimeScope();
builder.RegisterType<RewardPointService>().As<IRewardPointService>().InstancePerLifetimeScope();
builder.RegisterType<ShoppingCartService>().As<IShoppingCartService>().InstancePerLifetimeScope(); builder.RegisterType<PaymentService>().As<IPaymentService>().InstancePerLifetimeScope(); builder.RegisterType<EncryptionService>().As<IEncryptionService>().InstancePerLifetimeScope();
builder.RegisterType<FormsAuthenticationService>().As<IAuthenticationService>().InstancePerLifetimeScope(); //use static cache (between HTTP requests)
builder.RegisterType<UrlRecordService>().As<IUrlRecordService>()
.WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
.InstancePerLifetimeScope(); builder.RegisterType<ShipmentService>().As<IShipmentService>().InstancePerLifetimeScope();
builder.RegisterType<ShippingService>().As<IShippingService>().InstancePerLifetimeScope(); builder.RegisterType<TaxCategoryService>().As<ITaxCategoryService>().InstancePerLifetimeScope();
builder.RegisterType<TaxService>().As<ITaxService>().InstancePerLifetimeScope(); builder.RegisterType<DefaultLogger>().As<ILogger>().InstancePerLifetimeScope(); //use static cache (between HTTP requests)
builder.RegisterType<CustomerActivityService>().As<ICustomerActivityService>()
.WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
.InstancePerLifetimeScope(); bool databaseInstalled = DataSettingsHelper.DatabaseIsInstalled();
if (!databaseInstalled)
{
//installation service
if (config.UseFastInstallationService)
{
builder.RegisterType<SqlFileInstallationService>().As<IInstallationService>().InstancePerLifetimeScope();
}
else
{
builder.RegisterType<CodeFirstInstallationService>().As<IInstallationService>().InstancePerLifetimeScope();
}
} builder.RegisterType<ForumService>().As<IForumService>().InstancePerLifetimeScope(); builder.RegisterType<PollService>().As<IPollService>().InstancePerLifetimeScope();
builder.RegisterType<BlogService>().As<IBlogService>().InstancePerLifetimeScope();
builder.RegisterType<WidgetService>().As<IWidgetService>().InstancePerLifetimeScope();
builder.RegisterType<TopicService>().As<ITopicService>().InstancePerLifetimeScope();
builder.RegisterType<NewsService>().As<INewsService>().InstancePerLifetimeScope(); builder.RegisterType<DateTimeHelper>().As<IDateTimeHelper>().InstancePerLifetimeScope();
builder.RegisterType<SitemapGenerator>().As<ISitemapGenerator>().InstancePerLifetimeScope();
builder.RegisterType<PageHeadBuilder>().As<IPageHeadBuilder>().InstancePerLifetimeScope(); builder.RegisterType<ScheduleTaskService>().As<IScheduleTaskService>().InstancePerLifetimeScope(); builder.RegisterType<ExportManager>().As<IExportManager>().InstancePerLifetimeScope();
builder.RegisterType<ImportManager>().As<IImportManager>().InstancePerLifetimeScope();
builder.RegisterType<PdfService>().As<IPdfService>().InstancePerLifetimeScope();
builder.RegisterType<ThemeProvider>().As<IThemeProvider>().InstancePerLifetimeScope();
builder.RegisterType<ThemeContext>().As<IThemeContext>().InstancePerLifetimeScope(); builder.RegisterType<ExternalAuthorizer>().As<IExternalAuthorizer>().InstancePerLifetimeScope();
builder.RegisterType<OpenAuthenticationService>().As<IOpenAuthenticationService>().InstancePerLifetimeScope(); builder.RegisterType<RoutePublisher>().As<IRoutePublisher>().SingleInstance(); //Register event consumers
var consumers = typeFinder.FindClassesOfType(typeof(IConsumer<>)).ToList();
foreach (var consumer in consumers)
{
builder.RegisterType(consumer)
.As(consumer.FindInterfaces((type, criteria) =>
{
var isMatch = type.IsGenericType && ((Type)criteria).IsAssignableFrom(type.GetGenericTypeDefinition());
return isMatch;
}, typeof(IConsumer<>)))
.InstancePerLifetimeScope();
}
builder.RegisterType<EventPublisher>().As<IEventPublisher>().SingleInstance();
builder.RegisterType<SubscriptionService>().As<ISubscriptionService>().SingleInstance(); }

我的NopCommerce之旅(7): 依赖注入(IOC/DI)的更多相关文章

  1. 关于依赖注入IOC/DI的感想

    之前一直不明白依赖注入有什么好处,甚至觉得它是鸡肋,现在想想,当时真是可笑. 这个想法正如同说接口是没有用处一样. 当整个项目非常庞大,各个方法之间的调用非常复杂,那么,可以想象一下,假设说没有任何的 ...

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

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

  3. ASP.NET Core中的依赖注入(2):依赖注入(DI)

    IoC主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...

  4. 控制反转(IOC: Inverse Of Control) & 依赖注入(DI: Independence Inject)

    举例:在每天的日常生活中,我们离不开水,电,气.在城市化之前,我们每家每户需要自己去搞定这些东西:自己挖水井取水,自己点煤油灯照明,自己上山砍柴做饭.而城市化之后,人们从这些琐事中解放了出来,城市中出 ...

  5. Spring学习3—控制反转(IOC)Spring依赖注入(DI)和控制反转(IOC)

    一.思想理解 Spring 能有效地组织J2EE应用各层的对象.不管是控制层的Action对象,还是业务层的Service对象,还是持久层的DAO对象,都可在Spring的 管理下有机地协调.运行.S ...

  6. 控制反转(IOC)和依赖注入(DI)的区别

    IOC   inversion of control  控制反转 DI   Dependency Injection  依赖注入 要理解这两个概念,首先要搞清楚以下几个问题: 参与者都有谁? 依赖:谁 ...

  7. Spring的依赖注入(DI)三种方式

    Spring依赖注入(DI)的三种方式,分别为: 1.  接口注入 2.  Setter方法注入 3.  构造方法注入 下面介绍一下这三种依赖注入在Spring中是怎么样实现的. 首先我们需要以下几个 ...

  8. Spring 反转控制(IOC) 依赖注入(DI)

    简单的理解: 之前是我为了完成业务A 需要某个对象B的支持 那么我在这个业务A中就会创建一个对象B使用,说白了就是我根据需求来控制对象B, 而spring的ioc把对象B的控制权从业务A手中拿到自己手 ...

  9. 添加EF上下文对象,添加接口、实现类以及无处不在的依赖注入(DI)

    添加EF上下文对象,添加接口.实现类以及无处不在的依赖注入(DI) 目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 上一章,我们介绍了安装和新建控制器.视图,这一章我们来创建 ...

随机推荐

  1. js获取浏览器宽高、网页宽高、屏幕宽高、鼠标位置等(带图片说明)

    网页可见区域宽: document.body.clientWidth;网页可见区域高: document.body.clientHeight;(点击查看大图) 网页可见区域宽: document.bo ...

  2. WebRTC学习

    1.     WebRTC学习 1.1   WebRTC现状 本人最早接触WebRTC是在2011年底,那时Google已经在Android源码中加入了webrtc源码,放在/external/web ...

  3. Java网络编程Socket通信

        TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议     UDP (User Datagram Proto ...

  4. 「LuoguP4147」 玉蟾宫(并查集

    题目背景 有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地. 题目描述 这片土地被分成N*M个格子,每个格子里写着'R'或者'F ...

  5. codevs 2456栅栏

    传送门 2456 栅栏 2006年省队选拔赛四川  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 大师 Maste   题目描述 Description 农夫约翰打算建立一个栅 ...

  6. Git 常用命令学习

    本文转载自:https://buptldy.github.io/2016/03/02/2016-03-02-Git%20Cheat%20Sheet/ 文章 创建版本库 初始化一个Git仓库,使用git ...

  7. AQS与重入锁ReetrantLock原理

    一.AQS原理 AQS(AbstractQueuedSynchronizer)队列同步器是用来构建锁.同步组件的基础框架. AQS内部通过一个volatile int类型的成员变量state控制同步状 ...

  8. Azure AD (6) 停止Azure AD Connect Sync同步,并删除自定义域名

    <Windows Azure Platform 系列文章目录> 如果你已经了解了我之前写的文章:Azure AD (5) 在单一目录下,使用Azure AD单点登录 应该对使用Azure ...

  9. HDOJ-1391

    Number Steps Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  10. MVC 基本工具(Visual Studio 的单元测试、使用Moq)

    3.Visual Studio 的单元测试 有很多.NET单元测试包,其中很多是开源和免费的.本文打算使用 Visual Studio 附带的内建单元测试支持,但其他一些.NET单元测试包也是可用的. ...