abp-ConsoleProject
附上一个学习网站:C#高级知识点&(ABP框架理论学习高级篇)——白金版 - tkbSimplest - 博客园 (cnblogs.com)
1.引入ABP
2.添加自定义module,继承AbpModule
public class MyAbpModule : AbpModule { public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); } } }
3,添加自己的service,继承ITransientDependency
//[Dependency(ServiceLifetime.Transient)] public class Service : ITransientDependency { public void Run() { Console.WriteLine("你好"); } }
4.具体实现
static void Main(string[] args) { using (var bootstrapper = AbpBootstrapper.Create<MyAbpModule>()) { bootstrapper.Initialize(); var service = IocManager.Instance.Resolve<Service>(); service.Run(); Console.ReadKey(); } }
相关分析,
01 AbpBootstrapper:构造函数时私有化的,只能通过Create方法获取实例
/// <summary> /// Creates a new <see cref="AbpBootstrapper"/> instance. /// </summary> /// <param name="startupModule">Startup module of the application which depends on other used modules. Should be derived from <see cref="AbpModule"/>.</param> /// <param name="optionsAction">An action to set options</param> private AbpBootstrapper( [NotNull] Type startupModule, [CanBeNull] Action<AbpBootstrapperOptions> optionsAction = null) { Check.NotNull(startupModule, nameof(startupModule)); var options = new AbpBootstrapperOptions(); optionsAction?.Invoke(options); if (!typeof(AbpModule).GetTypeInfo().IsAssignableFrom(startupModule)) { throw new ArgumentException($"{nameof(startupModule)} should be derived from {nameof(AbpModule)}."); } StartupModule = startupModule; IocManager = options.IocManager; PlugInSources = options.PlugInSources; _logger = NullLogger.Instance; AddInterceptorRegistrars(options.InterceptorOptions); }
看一下create方法,实例化AbpBootstrapper,字段,属性赋值。
/// <summary> /// Creates a new <see cref="AbpBootstrapper"/> instance. /// </summary> /// <typeparam name="TStartupModule">Startup module of the application which depends on other used modules. Should be derived from <see cref="AbpModule"/>.</typeparam> /// <param name="optionsAction">An action to set options</param> public static AbpBootstrapper Create<TStartupModule>( [CanBeNull] Action<AbpBootstrapperOptions> optionsAction = null) where TStartupModule : AbpModule { return new AbpBootstrapper(typeof(TStartupModule), optionsAction); }
02.AbpModule:
看下源码:
/// <summary> /// This class must be implemented by all module definition classes.
/// 该类必须由所有模块定义类实现。 /// </summary> /// <remarks> /// A module definition class is generally located in its own assembly /// and implements some action in module events on application startup and shutdown. /// It also defines depended modules. /// </remarks> public abstract class AbpModule { /// <summary> /// Gets a reference to the IOC manager. /// </summary> protected internal IIocManager IocManager { get; internal set; } /// <summary> /// Gets a reference to the ABP configuration. /// </summary> protected internal IAbpStartupConfiguration Configuration { get; internal set; } /// <summary> /// Gets or sets the logger. /// </summary> public ILogger Logger { get; set; } protected AbpModule() { Logger = NullLogger.Instance; } /// <summary> /// This is the first event called on application startup. /// Codes can be placed here to run before dependency injection registrations.
///这是应用程序启动时调用的第一个事件。
///代码可以放在这里,以便在依赖项注入注册之前运行。
/// </summary> public virtual void PreInitialize() { } /// <summary> /// This method is used to register dependencies for this module.此方法用于注册此模块的依赖项 /// </summary> public virtual void Initialize() { } /// <summary> /// This method is called lastly on application startup.最后在应用程序启动时调用此方法。 /// </summary> public virtual void PostInitialize() { } /// <summary> /// This method is called when the application is being shutdown.最后在应用程序关闭时调用此方法。 /// </summary> public virtual void Shutdown() { } public virtual Assembly[] GetAdditionalAssemblies() { return new Assembly[0]; } /// <summary> /// Checks if given type is an Abp module class. /// </summary> /// <param name="type">Type to check</param> public static bool IsAbpModule(Type type) { var typeInfo = type.GetTypeInfo(); return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType && typeof(AbpModule).IsAssignableFrom(type); } /// <summary> /// Finds direct depended modules of a module (excluding given module). /// </summary> public static List<Type> FindDependedModuleTypes(Type moduleType) { if (!IsAbpModule(moduleType)) { throw new AbpInitializationException("This type is not an ABP module: " + moduleType.AssemblyQualifiedName); } var list = new List<Type>(); if (moduleType.GetTypeInfo().IsDefined(typeof(DependsOnAttribute), true)) { var dependsOnAttributes = moduleType.GetTypeInfo().GetCustomAttributes(typeof(DependsOnAttribute), true).Cast<DependsOnAttribute>(); foreach (var dependsOnAttribute in dependsOnAttributes) { foreach (var dependedModuleType in dependsOnAttribute.DependedModuleTypes) { list.Add(dependedModuleType); } } } return list; } public static List<Type> FindDependedModuleTypesRecursivelyIncludingGivenModule(Type moduleType) { var list = new List<Type>(); AddModuleAndDependenciesRecursively(list, moduleType); list.AddIfNotContains(typeof(AbpKernelModule)); return list; } private static void AddModuleAndDependenciesRecursively(List<Type> modules, Type module) { if (!IsAbpModule(module)) { throw new AbpInitializationException("This type is not an ABP module: " + module.AssemblyQualifiedName); } if (modules.Contains(module)) { return; } modules.Add(module); var dependedModules = FindDependedModuleTypes(module); foreach (var dependedModule in dependedModules) { AddModuleAndDependenciesRecursively(modules, dependedModule); } } }
03.IocManager
看下源码:
/// <summary> /// This class is used to directly perform dependency injection tasks. /// </summary> public class IocManager : IIocManager { /// <summary> /// The Singleton instance. /// </summary> public static IocManager Instance { get; private set; } /// <summary> /// Singletone instance for Castle ProxyGenerator. /// From Castle.Core documentation it is highly recomended to use single instance of ProxyGenerator to avoid memoryleaks and performance issues /// Follow next links for more details: /// <a href="https://github.com/castleproject/Core/blob/master/docs/dynamicproxy.md">Castle.Core documentation</a>, /// <a href="http://kozmic.net/2009/07/05/castle-dynamic-proxy-tutorial-part-xii-caching/">Article</a> /// </summary> private static readonly ProxyGenerator ProxyGeneratorInstance = new ProxyGenerator(); /// <summary> /// Reference to the Castle Windsor Container. /// </summary> public IWindsorContainer IocContainer { get; private set; } /// <summary> /// List of all registered conventional registrars. /// </summary> private readonly List<IConventionalDependencyRegistrar> _conventionalRegistrars; static IocManager() { Instance = new IocManager(); } /// <summary> /// Creates a new <see cref="IocManager"/> object. /// Normally, you don't directly instantiate an <see cref="IocManager"/>. /// This may be useful for test purposes. /// </summary> public IocManager() { IocContainer = CreateContainer(); _conventionalRegistrars = new List<IConventionalDependencyRegistrar>(); //Register self! IocContainer.Register( Component .For<IocManager, IIocManager, IIocRegistrar, IIocResolver>() .Instance(this) ); } protected virtual IWindsorContainer CreateContainer() { return new WindsorContainer(new DefaultProxyFactory(ProxyGeneratorInstance)); } /// <summary> /// Adds a dependency registrar for conventional registration. /// </summary> /// <param name="registrar">dependency registrar</param> public void AddConventionalRegistrar(IConventionalDependencyRegistrar registrar) { _conventionalRegistrars.Add(registrar); } /// <summary> /// Registers types of given assembly by all conventional registrars. See <see cref="AddConventionalRegistrar"/> method. /// </summary> /// <param name="assembly">Assembly to register</param> public void RegisterAssemblyByConvention(Assembly assembly) { RegisterAssemblyByConvention(assembly, new ConventionalRegistrationConfig()); } /// <summary> /// Registers types of given assembly by all conventional registrars. See <see cref="AddConventionalRegistrar"/> method. /// </summary> /// <param name="assembly">Assembly to register</param> /// <param name="config">Additional configuration</param> public void RegisterAssemblyByConvention(Assembly assembly, ConventionalRegistrationConfig config) { var context = new ConventionalRegistrationContext(assembly, this, config); foreach (var registerer in _conventionalRegistrars) { registerer.RegisterAssembly(context); } if (config.InstallInstallers) { IocContainer.Install(FromAssembly.Instance(assembly)); } } /// <summary> /// Registers a type as self registration. /// </summary> /// <typeparam name="TType">Type of the class</typeparam> /// <param name="lifeStyle">Lifestyle of the objects of this type</param> public void Register<TType>(DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton) where TType : class { IocContainer.Register(ApplyLifestyle(Component.For<TType>(), lifeStyle)); } /// <summary> /// Registers a type as self registration. /// </summary> /// <param name="type">Type of the class</param> /// <param name="lifeStyle">Lifestyle of the objects of this type</param> public void Register(Type type, DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton) { IocContainer.Register(ApplyLifestyle(Component.For(type), lifeStyle)); } /// <summary> /// Registers a type with it's implementation. /// </summary> /// <typeparam name="TType">Registering type</typeparam> /// <typeparam name="TImpl">The type that implements <typeparamref name="TType"/></typeparam> /// <param name="lifeStyle">Lifestyle of the objects of this type</param> public void Register<TType, TImpl>(DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton) where TType : class where TImpl : class, TType { IocContainer.Register(ApplyLifestyle(Component.For<TType, TImpl>().ImplementedBy<TImpl>(), lifeStyle)); } /// <summary> /// Registers a type with it's implementation. /// </summary> /// <param name="type">Type of the class</param> /// <param name="impl">The type that implements <paramref name="type"/></param> /// <param name="lifeStyle">Lifestyle of the objects of this type</param> public void Register(Type type, Type impl, DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton) { IocContainer.Register(ApplyLifestyle(Component.For(type, impl).ImplementedBy(impl), lifeStyle)); } /// <summary> /// Checks whether given type is registered before. /// </summary> /// <param name="type">Type to check</param> public bool IsRegistered(Type type) { return IocContainer.Kernel.HasComponent(type); } /// <summary> /// Checks whether given type is registered before. /// </summary> /// <typeparam name="TType">Type to check</typeparam> public bool IsRegistered<TType>() { return IocContainer.Kernel.HasComponent(typeof(TType)); } /// <summary> /// Gets an object from IOC container. /// Returning object must be Released (see <see cref="IIocResolver.Release"/>) after usage. /// </summary> /// <typeparam name="T">Type of the object to get</typeparam> /// <returns>The instance object</returns> public T Resolve<T>() { return IocContainer.Resolve<T>(); } /// <summary> /// Gets an object from IOC container. /// Returning object must be Released (see <see cref="Release"/>) after usage. /// </summary> /// <typeparam name="T">Type of the object to cast</typeparam> /// <param name="type">Type of the object to resolve</param> /// <returns>The object instance</returns> public T Resolve<T>(Type type) { return (T)IocContainer.Resolve(type); } /// <summary> /// Gets an object from IOC container. /// Returning object must be Released (see <see cref="IIocResolver.Release"/>) after usage. /// </summary> /// <typeparam name="T">Type of the object to get</typeparam> /// <param name="argumentsAsAnonymousType">Constructor arguments</param> /// <returns>The instance object</returns> public T Resolve<T>(object argumentsAsAnonymousType) { return IocContainer.Resolve<T>(Arguments.FromProperties(argumentsAsAnonymousType)); } /// <summary> /// Gets an object from IOC container. /// Returning object must be Released (see <see cref="IIocResolver.Release"/>) after usage. /// </summary> /// <param name="type">Type of the object to get</param> /// <returns>The instance object</returns> public object Resolve(Type type) { return IocContainer.Resolve(type); } /// <summary> /// Gets an object from IOC container. /// Returning object must be Released (see <see cref="IIocResolver.Release"/>) after usage. /// </summary> /// <param name="type">Type of the object to get</param> /// <param name="argumentsAsAnonymousType">Constructor arguments</param> /// <returns>The instance object</returns> public object Resolve(Type type, object argumentsAsAnonymousType) { return IocContainer.Resolve(type, Arguments.FromProperties(argumentsAsAnonymousType)); } ///<inheritdoc/> public T[] ResolveAll<T>() { return IocContainer.ResolveAll<T>(); } ///<inheritdoc/> public T[] ResolveAll<T>(object argumentsAsAnonymousType) { return IocContainer.ResolveAll<T>(Arguments.FromProperties(argumentsAsAnonymousType)); } ///<inheritdoc/> public object[] ResolveAll(Type type) { return IocContainer.ResolveAll(type).Cast<object>().ToArray(); } ///<inheritdoc/> public object[] ResolveAll(Type type, object argumentsAsAnonymousType) { return IocContainer.ResolveAll(type, Arguments.FromProperties(argumentsAsAnonymousType)).Cast<object>().ToArray(); } /// <summary> /// Releases a pre-resolved object. See Resolve methods. /// </summary> /// <param name="obj">Object to be released</param> public void Release(object obj) { IocContainer.Release(obj); } /// <inheritdoc/> public void Dispose() { IocContainer.Dispose(); } private static ComponentRegistration<T> ApplyLifestyle<T>(ComponentRegistration<T> registration, DependencyLifeStyle lifeStyle) where T : class { switch (lifeStyle) { case DependencyLifeStyle.Transient: return registration.LifestyleTransient(); case DependencyLifeStyle.Singleton: return registration.LifestyleSingleton(); default: return registration; } } }
04.ITransientDependency
/// <summary> /// All classes implement this interface are automatically registered to dependency injection as transient object.
/// 实现此接口的所有类都将作为临时对象自动注册到依赖项注入。 /// </summary> public interface ITransientDependency { }