出售域名 11365.com.cn
有需要请联系 16826375@qq.com
在手机上浏览
在手机上浏览

Autofac的使用说明

发布日期:2019-12-31

楔子:吃东西的故事
Autofac是一款IOC容器,适用于.NET开发的高效管理依赖关系的组件。
在面向对象的软件开发概念中,有个依赖倒置原则,包含如下的三层含义:
1)高层模块不应该依赖低层模块,两者都应该依赖其抽象
2)抽象不应该依赖细节
3)细节应该依赖抽象
这个可能理解起来可能不是很容易,打个比方说,你饿了要吃东西,去店里点餐,告诉店老板只要能填饱肚了的就可以,那可以吃米饭、面食、甜点、大饼、包子……。总之选择很多,适应性强。但如果你说只吃面,不好意思,我这里只卖包子。去下一家,不好意思,我们只做客家菜……。可能走了一条街都没吃上东西。
软件的开闭原则告诉我们“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的”。如果一个模块一个对象可以预料是变化的,那就要能适应变化,所依赖的不能是具体的实现,否则需求变化了就不得不修改这个模块,违反了开闭原则,
如果按上面的需求写个代码应该写成:

namespace WebApp.Code
{
    public interface IFood
    {
        String FoodName { get;}
    }
    public class People
    {
        IFood _something;
        public People(IFood something)
        {
            this._something = something;
        }
        public void Eat()
        {
            Console.Write("吃" + _something.FoodName);
        }
    }
    public class 包子 : IFood
    {
        public string FoodName => "包子";
    }
    public class 拉面 : IFood
    {
        public string FoodName => "拉面";
    }
}


传统的实例化对象是new 一个对象

var p = new People(new 包子());
p.Eat();


也许有比包子更好吃的东西呢?何不学学梁山好汉“好酒好肉尽管上”!这就是注入的概念,

 

二、正文
Autofac官方文档:https://autofaccn.readthedocs.io/zh/latest/
其实文档已经很详细了,首先在项目中右键打开NuGet添加Autofac组件:

Autofac是主要的引用。
Autofac.Mvc5是对MVC的扩展引用。

Autofac的使用步骤包括三步:
1)注册
Autofac是一个IOC容器,既然是容器,就要往里面填东西。

//先定义这个容器
static IContainer Container { get; set; }
//然后通过注册往这个容器里填东西
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<ConsoleOutput>().As<IOutput>();
builder.RegisterType<TodayWrite>().As<IDateWriter>();
Container = builder.Build();

2)解析

using (var scope = Container.BeginLifetimeScope())
{
    var writer = scope.Resolve<IDateWriter>();
    //...
}


3) 使用

writer.WriteDate();

 

更多用法:

enum MyEnum
{
    cn,
    en
}
public interface ISpeak
{
    void Say(string content);
}
public class ChineseSpeaker : ISpeak
{
    string _param = "";
    public ChineseSpeaker(string param)
    {
        this._param = param;
    }
    public void Say(string content)
    {
        Console.WriteLine(_param + "中国人说:" + content);
    }
}
public class EnglishSpeaker : ISpeak
{
    public void Say(string content)
    {
        Console.WriteLine("英国人说:" + content);
    }
}

注册多个相同类型的对象,需要用命名区分:

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<ChineseSpeaker>().Named<ISpeak>("cn");
builder.RegisterType<EnglishSpeaker>().Named<ISpeak>("en");

Container = builder.Build();
var sc = Container.ResolveNamed<ISpeak>("en");
sc.Say("Hello!");

注册多个相同类型并带有参数

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<ChineseSpeaker>().Keyed<ISpeak>(MyEnum.cn).SingleInstance();
builder.RegisterType<EnglishSpeaker>().Keyed<ISpeak>(MyEnum.en).InstancePerDependency();

Container = builder.Build();
var sc = Container.ResolveKeyed<ISpeak>(MyEnum.cn,new NamedParameter("param", "哈哈!"));
sc.Say("您好!");

 

Autofac在MVC中的使用(这里使用的是MVC5)

首先在全局类中注册:

public class MvcApplication : System.Web.HttpApplication
{
    private void SetupResolveRules(ContainerBuilder builder)
    {
        builder.RegisterType<PersonRepository>().As<IPersonRepository>();
        builder.RegisterType<CMS>().As<ICMS>();
    }

    protected void Application_Start()
    {
        var builder = new ContainerBuilder();
        SetupResolveRules(builder);
        builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
        var container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

        AreaRegistration.RegisterAllAreas();
        RouteConfig.RegisterRoutes(RouteTable.Routes);
    }
}

1)在控制器(Controller)中使用

public class DefaultController : Controller
{
    public IPersonRepository Repository { get; set; }

    // GET: Default
    public ActionResult Index()
    {
        var data = Repository.GetAll();
        ViewBag.Users = data;

        return View();
    }
}

在视图中可以通过 foreach(var item in ViewBag.Users)进行遍历。

2)在视图(View)中使用

也可以直接在视图中使用:

@{
    ViewBag.Title = "Default";
    var users = DependencyResolver.Current.GetService<WebApp.Code.IPersonRepository>();
    var cms = DependencyResolver.Current.GetService<WebApp.Code.ICMS>();
}

<h2>Default</h2>
@{
    foreach (var item in users.GetAll())
    {
        <p>用户名: + @item.Name;</p>
    }
}

<p>cms</p>
@(cms.WriteSomething())