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";
        }
    }
}

運行之後我們就能看到效果了

發佈了2 篇原創文章 · 獲贊 0 · 訪問量 93
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章