IOC - AOP - AutoFac

DI(依赖注入) 是 IOC 的一种方案.

AutoFac 是 DI 的一种具体实现方式.

 

从没有套用 AutoFac 的例子开始看起

public interface IClass
{
    string Fun();
}
public class ClassA : IClass
{
    public string Fun()
    {
        return "Class1";
    }
}
public class ClassB : IClass
{
    public string Fun()
    {
        return "Class2";
    }
}

 

用一个管理器来调用上述类

public class Fac
{
   public static IClass GetClass() { return new ClassA(); } }

 

设置一个运行入口, 来使用管理器

static void Main(string[] args)
{
    var i = Fac.GetClass();
Console.WriteLine(i.Fun()); Console.ReadKey(); }

 

 

套用 AutoFac  的例子

public class Manager
{
    Interface1 p;
  
    public Manager(Interface1 _p)
    {
        p = _p
    }

    public string str()
    {
        return p.print();
    }
}

 

设置一个运行入口, 来使用管理器

static void Main(string[] args)
{
   /* --------------------------------------------
var builder = new ContainerBuilder(); builder.RegisterType<Class1>().AsImplementedInterfaces(); builder.RegisterType<Manager>();
var _container = builder.Build(); var _m = _container.Resolve<Manager>(); ----------------------------------------------*/
//Manager a = new Manager(); Console.WriteLine(_m.str()); Console.ReadKey(); }

 

目前为止, 调用者解除了对 Fac 控制器的依赖, 转而使用 DI 来代替 Fac 管理 (实际效果差不多, DI倾向于注入的概念).

 

调用者在被其他类使用的过程中, 便不需要知道自己该调用哪个具体类了,

直接由 Builder 来对调用者的构造函数进行注入决定.

至于是如何决定的, 这来源于 Builder 进行 Register(注册) 时就决定了 (最后一个注册的实体对象覆盖前面注册的对象)

 

 

 

mvc 要使用 autofac 的话

引用 Autofac

引用 Autofac.Mvc5

需要先创建一个 IDependency 接口

然后

protected void Application_Start()
{
    // 创建容器
    var builder = new ContainerBuilder();
    // 依据 IDependency 来映射
    var baseType = typeof(IDependency);
    // 获取当前项目所有的程序集
    var assemblys = AppDomain.CurrentDomain.GetAssemblies().ToList();
    // 获取所有 实现 IDependency 的类
    //var AllServices = assemblys
    //    .SelectMany(s => s.GetTypes())
    //    .Where(p => baseType.IsAssignableFrom(p) && p != baseType);

    // 注册 DbContext的映射规则 : 同一个生命周期内(可以理解成方法体内)生成的是同一个实例
    builder.RegisterType<P2PDb2Context>().InstancePerLifetimeScope();
    // 注册 Repository 的映射
    builder.RegisterGeneric(typeof(Repository<,>)).As(typeof(IRepository<,>));
    // 注册所有 Controller 的映射(针对 Controller 的构造函数)
    builder.RegisterControllers(assemblys.ToArray());
    //builder.RegisterApiControllers(assemblys.ToArray());
    // 注册所有实现 IDependency 的类
    builder.RegisterAssemblyTypes(assemblys.ToArray())
        .Where(t => baseType.IsAssignableFrom(t) && t != baseType)
        // 这里的AsImplementedInterfaces表示以接口的形式注册
        .AsImplementedInterfaces()
        // 同一个生命周期内(可以理解成方法体内)生成的是同一个实例
        .InstancePerLifetimeScope();

    var container = builder.Build();
    // 加入反射配置中
    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));


    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    AutoMapperConfig.Config();
}

 

WebApi 要用 Autofac 的话 

引用 Autofac

引用 Autofac.WebApi2

 

AOP Interceptor

实现AOP主要由两种方式,一种是编译时静态植入,优点是效率高,缺点是缺乏灵活性,.net下postsharp为代表者(这个是收费的)。另一种方式是动态代理,优缺点与前者相反,动态为目标类型创建代理,通过代理调用实现拦截

Autofac的AOP是通过Castle(也是一个容器)项目的核心部分实现的,名为Autofac.Extras.DynamicProxy,顾名思义,其实现方式为动态代理。

/// <summary>
///  1. 拦截器 需要实现 IInterceptor接口 Intercept方法
/// </summary>
class LogInterceptor : IInterceptor
{
    /// <summary>
    ///  拦截方法 打印被拦截的方法执行前的名称、参数和方法执行后的 返回结果
    /// </summary>
    /// <param name="invocation">包含被拦截方法的信息</param>
    public void Intercept(IInvocation invocation)
    {
        Debug.WriteLine("{0}:拦截{1}方法{2}前,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
        // //在被拦截的方法执行完毕后 继续执行
        invocation.Proceed();
        Debug.WriteLine("{0}:拦截{1}方法{2}后,", DateTime.Now.ToString("O"), invocation.InvocationTarget.GetType().BaseType, invocation.Method.Name);
    }
}

MVC的话

var builder = new ContainerBuilder();
// 2. 注册拦截器到Autofac容器
// 拦截器必须注册到Aufofac容器中,可以通过拦截器类型或者命名注入,这两种方式会让使用拦截器的方法有所不同
// (命名注入) builder.Register(c => new CallLogger(Console.Out)).Named<IInterceptor>("log-calls");
// (类型注入) builder.Register(c => new CallLogger(Console.Out)); 

// 3. 启用拦截器
// 启用拦截器主要有两个方法:EnableInterfaceInterceptors(),EnableClassInterceptors()。
// EnableInterfaceInterceptors方法会动态创建一个接口代理
// EnableClassInterceptors方法会创建一个目标类的子类代理类,这里需要注意的是只会拦截虚方法,重写方法

// 4. 指明要拦截的类型
// 有两种方法
// 给类型加上特性 Attribute [Intercept(typeof(Person))]
// 在注册类型到容器的时候动态注入拦截器  .InterceptedBy(typeof(LogInterceptor))
builder.RegisterType<Person>().As<IPerson>().EnableInterfaceInterceptors().InterceptedBy(typeof(LogInterceptor));
builder.RegisterControllers(assemblys.ToArray());
builder.RegisterType<LogInterceptor>();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

 

 

var builder = new ContainerBuilder();

// Mvc Register
builder.RegisterControllers(Assembly.GetExecutingAssembly()).AsSelf().PropertiesAutowired();
builder.RegisterFilterProvider();
builder.RegisterType<UserService>().As<IUserService>().InstancePerLifetimeScope();

//WebApi Register
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).AsSelf().PropertiesAutowired();
builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
builder.RegisterWebApiModelBinderProvider();

var container = builder.Build();

// Set the dependency resolver for Web API.
var webApiResolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = webApiResolver;

// Set the dependency resolver for MVC.
var resolver = new AutofacDependencyResolver(container);
DependencyResolver.SetResolver(resolver);

 

 

 

 

 

 

 

 

 

 

注册框架

// 创建一个容器
var builder = new ContainerBuilder();

/* do something */

// 把容器装入到微软默认的依赖注入容器中(MVC)
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

 

注册对象

// 注册控制器
builder.RegisterControllers(Assembly.GetExecutingAssembly());

// 注册Api
builder.RegisterApiControllers(assemblys.ToArray())

// 注册类
builder.RegisterType<InjectionTestService>();
builder.Register(c => new InjectionTestService());

// 注册泛型类
builder.RegisterGeneric(typeof(Repository<,>)).As(typeof(IRepository<,>));

// 注册程序集
builder.RegisterAssemblyTypes(assemblys.ToArray())

 

注入本身 .AsSelf()

为接口注入具体类

 

生命周期

1、InstancePerDependency

对每一个依赖或每一次调用创建一个新的唯一的实例。这也是默认的创建实例的方式。

官方文档解释:Configure the component so that every dependent component or call to Resolve() gets a new, unique instance (default.) 

2、InstancePerLifetimeScope

在一个生命周期域中,每一个依赖或调用创建一个单一的共享的实例,且每一个不同的生命周期域,实例是唯一的,不共享的。

官方文档解释:Configure the component so that every dependent component or call to Resolve() within a single ILifetimeScope gets the same, shared instance. Dependent components in different lifetime scopes will get different instances. 

3、InstancePerMatchingLifetimeScope

在一个做标识的生命周期域中,每一个依赖或调用创建一个单一的共享的实例。打了标识了的生命周期域中的子标识域中可以共享父级域中的实例。若在整个继承层次中没有找到打标识的生命周期域,则会抛出异常:DependencyResolutionException

官方文档解释:Configure the component so that every dependent component or call to Resolve() within a ILifetimeScope tagged with any of the provided tags value gets the same, shared instance. Dependent components in lifetime scopes that are children of the tagged scope will share the parent's instance. If no appropriately tagged scope can be found in the hierarchy an DependencyResolutionException is thrown. 

4、InstancePerOwned

在一个生命周期域中所拥有的实例创建的生命周期中,每一个依赖组件或调用Resolve()方法创建一个单一的共享的实例,并且子生命周期域共享父生命周期域中的实例。若在继承层级中没有发现合适的拥有子实例的生命周期域,则抛出异常:DependencyResolutionException

官方文档解释:Configure the component so that every dependent component or call to Resolve() within a ILifetimeScope created by an owned instance gets the same, shared instance. Dependent components in lifetime scopes that are children of the owned instance scope will share the parent's instance. If no appropriate owned instance scope can be found in the hierarchy an DependencyResolutionException is thrown. 

5、SingleInstance

每一次依赖组件或调用Resolve()方法都会得到一个相同的共享的实例。其实就是单例模式。

官方文档解释:Configure the component so that every dependent component or call to Resolve() gets the same, shared instance. 

6、InstancePerHttpRequest  (新版autofac建议使用InstancePerRequest)

在一次Http请求上下文中,共享一个组件实例。仅适用于asp.net mvc开发。
官方文档解释:Share one instance of the component within the context of a single HTTP request.

参考地址: https://www.cnblogs.com/struggle999/p/6986903.html

 

posted @ 2015-07-20 17:25  `Laimic  阅读(463)  评论(0)    收藏  举报