.NET中的dependency injection的例子?
有人可以用 一个基本的.NET例子解释dependency injection ,并提供一些到.NET资源的链接来扩展这个主题吗?
这不是什么dependency injection的重复? 因为我在问具体的.NET示例和资源。
这是一个常见的例子。 您需要login您的应用程序。 但是,在devise时,您不确定客户端是否要logging到数据库,文件或事件日志。
所以,你想使用DI来推迟这个select,可以由客户端configuration。
这是一些伪代码(大致基于Unity):
你创build一个日志界面:
public interface ILog { void Log(string text); }
然后在你的类中使用这个接口
public class SomeClass { [Dependency] public ILog Log {get;set;} }
在运行时注入这些依赖关系
public class SomeClassFactory { public SomeClass Create() { var result = new SomeClass(); DependencyInjector.Inject(result); return result; } }
并在app.config中configuration实例:
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <section name ="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/> </configSections> <unity> <typeAliases> <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,Microsoft.Practices.Unity" /> </typeAliases> <containers> <container> <types> <type type="MyAssembly.ILog,MyAssembly" mapTo="MyImplementations.SqlLog, MyImplementations"> <lifetime type="singleton"/> </type> </types> </container> </containers> </unity> </configuration>
现在,如果您想更改logging器的types,只需进入configuration并指定其他types。
Ninject必须有一个最酷的样本:(从样本中拼凑出来)
interface IWeapon { void Hit(string target); } class Sword : IWeapon { public void Hit(string target) { Console.WriteLine("Chopped {0} clean in half", target); } } class Shuriken : IWeapon { public void Hit(string target) { Console.WriteLine("Shuriken tossed on {0}", target); } } class Samurai { private IWeapon _weapon; [Inject] public Samurai(IWeapon weapon) { _weapon = weapon; } public void Attack(string target) { _weapon.Hit(target); } } class WeaponsModule: NinjectModule { private readonly bool _useMeleeWeapons; public WeaponsModule(bool useMeleeWeapons) { _useMeleeWeapons = useMeleeWeapons; } public void Load() { if (useMeleeWeapons) Bind<IWeapon>().To<Sword>(); else Bind<IWeapon>().To<Shuriken>(); } } class Program { public static void Main() { bool useMeleeWeapons = false; IKernel kernel = new StandardKernel(new WeaponsModule(useMeleeWeapons)); Samurai warrior = kernel.Get<Samurai>(); warrior.Attack("the evildoers"); } }
这对我来说,读得非常stream利,在开始你的道场之前,你可以决定如何武装你的武士。
我认为首先学习没有IoC容器的DI是非常重要的。 因此,我写了一个例子,缓慢build立一个IoC容器。 这是我工作中的一个真实例子,但对新手来说,抓住DI的本质还是很足够的。 你可以在这里find它: https : //dannyvanderkraan.wordpress.com/2015/06/15/real-world-example-of-dependeny-injection/
它使用C#.NET,稍后使用Unity。
更新后的评论:
文章的相关部分
“观察对原始devise的以下更改:
我们去“构造器注入”模式来实现DI,重构的步骤是:
- 通过创buildInterface ICardPresenceChecker来抽象CardPresenceChecker的接口;
- 明确指出,此CardPresenceChecker只能用于X公司的库,方法是将其名称更改为XCardPresenceChecker;
- 让XCardPresenceChecker实现Interface ICardPresenceChecker;
- 将LogInService的属性抽象为ICardPresenceCheckertypes的属性,而不是“确切地”知道哪个实现是在外部的;
- 最后但并非最不重要的一点是,LogInService的用户(其他开发者)要求他们提供至less实现ICardPresenceChecker的任何类,以便LogInService可以完成它的工作。
LogInService的构造函数如下所示:
this.myCardPresenceChecker = cardPresenceChecker; this.myCardPresenceChecker.CardIn += MyCardPresenceChecker_CardIn; this.myCardPresenceChecker.CardOut += MyCardPresenceChecker_CardOut; this.myCardPresenceChecker.Init();
那么您在哪里提供了一个ICardPresenceChecker的实现LogInService? 您通常需要在应用程序启动的一个中心位置(在此示例中,我们将'ICardPresenceChecker'映射到XCardPresenceChecker')映射(在概念上称为“组合根”)。 对于可能是Program类中的void Main的ol定期控制台应用程序。 所以对于这个例子,这段代码将被用在上述地方:
LogInService logInService = new LogInService(new XCardPresenceChecker());“
我有一个像这样一个非常简单的例子dependency injection。
看到下面的课程,你会得到整个想法。 正如你所看到的,除非你提供文件,它将使用默认的一个设置文件,但你可以设置一个设置文件,然后类将使用它。
Public Class ProcessFile Private _SettingsFile As String = "settings.bin" Public Sub New() End Sub Public Sub New(settings As String) _SettingsFile= settings End Sub Public Function ReadFile() As String 'Do stuff based on the settings stored in the _SettingsFile End Function End Class
显然这是最基本的情况。 在现实世界中,您可以对类types做同样的事情,例如您拥有数据库层,您可以通过执行dependency injection来切换底层数据库DLL,只要您可以提供有效的类,代码就可以与任何数据库一起工作(一个实现你正在使用的接口的类)。
在获得了基本的基础之后,您可以在更大的范围内完成此任务,并通过使用统一的DI框架完全独立于应用程序。
你必须在构造函数中传入所有必要的对象。 或者,您可以使用接口parsing器在运行时parsing它们(尽pipe这不是types安全的)。 您可以在Ninject网站上find第一种方法的优秀示例,以及第二种方法在Unity网站上的示例。 这避免了单例的需要,并允许您轻松地放入符合所需接口的replace对象
在主mvc4项目名称SampleDependency中安装Nuget包。 Unity.mvc4,unity.webapi和MicrosoftAsp.Net Web API 2.2 Web主机
在web项目
public static class Bootstrapper { public static IUnityContainer Initialise() { var container = BuildUnityContainer(); DependencyResolver.SetResolver(new UnityDependencyResolver(container)); GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container); return container; } private static IUnityContainer BuildUnityContainer() { var container = new UnityContainer(); // register all your components with the container here // it is NOT necessary to register your controllers // eg container.RegisterType<ITestService, TestService>(); container.RegisterType<IUserDetailLogic, UserDetailLogic>(); container.RegisterType<IUserData, UserData>(); RegisterTypes(container); return container; } public static void RegisterTypes(IUnityContainer container) { } }
添加类库types的商务逻辑项目,并在其中添加下面的代码。 公共类UserDetailLogic:IUserDetailLogic {私人IUserData _userData = null;
public UserDetailLogic(IUserData userData) { _userData = userData; } public string getUserDetails() { return _userData.getUserDetails(); } } public interface IUserDetailLogic { string getUserDetails(); }
在你的主项目中添加下面的代码在家里的控制器。
公共类HomeController:控制器{私人只读IUserDetailLogic _userDetailLogic;
public HomeController(IUserDetailLogic userDetailLogic) { _userDetailLogic = userDetailLogic; } public ActionResult Index() { ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application."; string str = _userDetailLogic.getUserDetails(); return View(); } public ActionResult About() { ViewBag.Message = "Your app description page."; return View(); } public ActionResult Contact() { ViewBag.Message = "Your contact page."; return View(); } }
创build数据库层项目(类库),并在其中添加下面的代码。
public class UserData : IUserData { public string getUserDetails() { return "Asif"; } } public interface IUserData { string getUserDetails(); }