c#MVC使用AutoFac实现IoC容器,接口多个实现的注入

AutoFac能够实现自动注入

AutoFac下载的引入

使用nuget包管理引入AutoFac

添加打勾的3个,AutoFac容器,AutoFac的apiController支持,AutoFac的mvc支持

在Global.asax中注册AutoFac

        protected void Application_Start()
        {
            Register(typeof(IService).Assembly);
        }

        protected void Register(params Assembly[] assemblys)
        {
            var builder = new ContainerBuilder();
            // 注册type接口的程序集中包含Service的接口
            builder.RegisterAssemblyTypes(assemblys).AsImplementedInterfaces();
            // 注册主项目的Controllers
            builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();

            // 注册主项目的ApiControllers
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
            builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
            builder.RegisterWebApiModelBinderProvider();
            // 获取注入容器
            var container = builder.Build();
            // 设置MVC的注入解析程序
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
            // 设置Api的注入解析程序
            GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
        }

其中IService是需要需要注入项目接口放置的程序集中的一个类,不需要实现

namespace Service
{
    public interface IService
    {
    }
}

使用AutoFac

在IService所在程序集添加一个接口类,一个实现类

namespace Service.Api
{
    public interface ITranslationService
    {
        string Lang();
    }
}



namespace Service.Impl
{
    public class TranslationServiceImpl : ITranslationService
    {
        public string Lang()
        {
            System.Diagnostics.Debug.WriteLine("调用成功");
        }
    }
}

在Controller中注入

namespace Aca.Certain.Web.Controllers
{
    public class PatientController : Controller
    {
        private readonly ITranslationService _translationService;

        public PatientController(ITranslationService translationService)
        {
            this._translationService = translationService;
        }

        public string text()
        {
            _translationService.Lang();
            return "success";
        }
    }
}

访问controller就能看到效果了

上面就是AutoFac的简单使用

但是,写过项目的人就会发现,光光上面那种使用方法,正真使用起来很鸡肋,经常有一个接口多个实现的情况出现,像上面那样使用就不行了

那么我们就来对程序进行一些修改,做到能想spring一样,根据名称获取要注入的类,并且不是所有的接口实现都需要依赖注入的,需要排除一些我们不需要的

定义Service注解

要有名称,首先要给接口实现一个名字,我们可以使用一个Attribute

namespace Common.Autofac
{
    public class ServiceAttribute : Attribute
    {
        private readonly string _name = "";

        public ServiceAttribute()
        {
            var a = this;
        }

        public ServiceAttribute(string name)
        {
            this._name = name;
        }

        public string Name
        {
            get { return _name; }
        }
    }
}

在Serveice是实现加上注解

namespace Service.Api
{
    public interface ITranslationService
    {
        string Lang();
    }
}



namespace Service.Impl
{
    [Service("service1")]
    public class TranslationServiceImpl : ITranslationService
    {
        public string Lang()
        {
            System.Diagnostics.Debug.WriteLine("调用1成功");
        }
    }
}

namespace Service.Impl
{
    [Service("service2")]
    public class TranslationServiceImpl : ITranslationService
    {
        public string Lang()
        {
            System.Diagnostics.Debug.WriteLine("调用2成功");
        }
    }
}

 写一个根据名称获取Service的方法

namespace Aca.Certain.Common.Autofac
{
    /// <summary>
    /// 基于Autofac的服务定位器
    /// </summary>
    public class ServiceLocator
    {
        private static Dictionary<string, object> _serviceDict = new Dictionary<string, object>();

        private static IContainer _container;

        /// <summary>
        /// 设置Ico容器
        /// </summary>
        /// <param name="container"></param>
        public static void SetContainer(IContainer container)
        {
            _container = container;
        }

        /// <summary>
        /// 获取容器对象
        /// </summary>
        /// <returns></returns>
        public static IContainer GetContainer()
        {
            return _container;
        }

        public static TService GetService<TService>()
        {
            return _container.Resolve<TService>();
        }

        /// <summary>
        /// 根据serviceName获取Service,不区分大小写
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <param name="serviceName"></param>
        /// <returns></returns>
        public static TService GetServiceByName<TService>(string serviceName)
        {
            serviceName = serviceName.ToLower();
            if (_serviceDict.ContainsKey(serviceName))
            {
                return (TService)_serviceDict[serviceName];
            }
            lock (serviceName)
            {
                if (_serviceDict.ContainsKey(serviceName))
                {
                    return (TService)_serviceDict[serviceName];
                }
                var list = AutofacDependencyResolver.Current.GetServices(typeof(TService));
                if (list.Count() == 0)
                {
                    throw new NullReferenceException(); ;
                }
                foreach (var item in list)
                {
                    Type type = item.GetType();
                    Attribute sa = type.GetCustomAttribute(typeof(ServiceAttribute));
                    if (sa != null)
                    {
                        if (((ServiceAttribute)sa).Name.ToLower() == serviceName.ToLower())
                        {
                            _serviceDict.Add(serviceName, item);
                            return (TService)item;
                        }
                    }
                }
                _serviceDict.Add(serviceName, list.ElementAt(0));
                return (TService)list.ElementAt(0);
            }
        }
    }
}

这个方法是根据name查找Service,没找到时,返回第一个

修改Global.asax中Register方法

protected void Register(params Assembly[] assemblys)
{
	var builder = new ContainerBuilder();
	// 注册type接口的程序集中包含Service的接口
	builder.RegisterAssemblyTypes(assemblys).Where(t =>
		t.GetCustomAttribute(typeof(ServiceAttribute)) != null
	).AsImplementedInterfaces();
	// 注册主项目的Controllers
	builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();

	// 注册主项目的ApiControllers
	builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
	builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
	builder.RegisterWebApiModelBinderProvider();
	// 获取注入容器
	var container = builder.Build();
	//设置服务容器
	ServiceLocator.SetContainer(container);
	// 设置MVC的注入解析程序
	DependencyResolver.SetResolver(new AutofacDependencyResolver(ServiceLocator.GetContainer()));
	// 设置Api的注入解析程序
	GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}

修改Controller

namespace Aca.Certain.Web.Controllers
{
    public class PatientController : Controller
    {
        private readonly ITranslationService _service1;
        private readonly ITranslationService _service2;

        public PatientController()
        {
            this._service1 = ServiceLocator.GetServiceByName<ITranslationService>("service1");
            this._service2 = ServiceLocator.GetServiceByName<ITranslationService>("service2");
        }

        public string text()
        {
            _service1.Lang();
            _service2.Lang();
            return "success";
        }
    }
}

运行之后我们就能看到效果了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值