Dependency Injection in .NET with examples?

前端 未结 8 1459
别跟我提以往
别跟我提以往 2020-11-27 14:31

Can someone explain dependency injection with a basic .NET example and provide a few links to .NET resources to extend on

相关标签:
8条回答
  • 2020-11-27 15:06

    I think it is important that you first learn DI without IoC Containers. So therefor I've written an example that slowly builts up to an IoC Container. It's a real example from my work, but still made basic enough for novices to grab the essence of DI. You can find it here: https://dannyvanderkraan.wordpress.com/2015/06/15/real-world-example-of-dependeny-injection/

    It's in C#.NET and later on it uses Unity.

    Update after comment:

    Relevant section of article

    "Observe the following changes to the original design:

    We went for the “Constructor Injection” pattern to implement DI and the refactoring steps were:

    1. Abstract the interface of CardPresenceChecker by creating Interface ICardPresenceChecker;
    2. Make explicit that this CardPresenceChecker only works for the library of Company X, by changing its name to XCardPresenceChecker ;
    3. Have XCardPresenceChecker implement Interface ICardPresenceChecker ;
    4. Abstract the property of LogInService to be of type ICardPresenceChecker instead of ‘knowing’ exactly which implementation is held aboard;
    5. And last but not least, demand from users (other developers) of LogInService that they provide any class that at least implements ICardPresenceChecker so that LogInService can do its thing.

    LogInService’s constructor looks like:

    this.myCardPresenceChecker = cardPresenceChecker;
    this.myCardPresenceChecker.CardIn += MyCardPresenceChecker_CardIn;
    this.myCardPresenceChecker.CardOut += MyCardPresenceChecker_CardOut;
    this.myCardPresenceChecker.Init();
    

    So where do you provide LogInService with an implementation of ICardPresenceChecker? You usually want this ‘mapping’ (in this example we would ‘map’ ICardPresenceChecker to XCardPresenceChecker) at one central place at the startup of an application, known conceptually as the “Composition Root”. For an ol’ regular Console Application that could be the void Main in the Program class. So for this example, this piece of code would be used at the aformentioned place:

    LogInService logInService = new LogInService(new XCardPresenceChecker());"

    0 讨论(0)
  • 2020-11-27 15:07

    Ninject must have one of the coolest sample out there: (pieced from the sample)

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

    This, to me, reads very fluently, before you start up your dojo you can decide how to arm your Samurais.

    0 讨论(0)
  • 2020-11-27 15:09

    Install below Nuget packages in main mvc4 project name SampleDependency. Unity.mvc4, unity.webapi and MicrosoftAsp.Net Web API 2.2 Web host

    In web project

    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
    
            // e.g. container.RegisterType<ITestService, TestService>();
            container.RegisterType<IUserDetailLogic, UserDetailLogic>();
            container.RegisterType<IUserData, UserData>();
    
            RegisterTypes(container);
    
            return container;
        }
        public static void RegisterTypes(IUnityContainer container)
        {
    
        }
    }
    
    0 讨论(0)
  • 2020-11-27 15:20

    You essentially pass in all necessary objects in the constructor. Alternatively, you can resolve them at runtime using an interface resolver (although this is less typesafe). You can find excellent examples at the Ninject website for the first approach, and good examples at the Unity website for the second approach. This avoid the need for singletons and allows you to easily drop in a replacement object that conforms to the desired interface

    0 讨论(0)
  • 2020-11-27 15:25

    Here's a common example. You need to log in your application. But, at design time, you're not sure if the client wants to log to a database, files, or the event log.

    So, you want to use DI to defer that choice to one that can be configured by the client.

    This is some pseudocode (roughly based on Unity):

    You create a logging interface:

    public interface ILog
    {
      void Log(string text);
    }
    

    then use this interface in your classes

    public class SomeClass
    {
      [Dependency]
      public ILog Log {get;set;}
    }
    

    inject those dependencies at runtime

    public class SomeClassFactory
    {
      public SomeClass Create()
      {
        var result = new SomeClass();
        DependencyInjector.Inject(result);
        return result;
      }
    }
    

    and the instance is configured in app.config:

    <?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>
    

    Now if you want to change the type of logger, you just go into the configuration and specify another type.

    0 讨论(0)
  • 2020-11-27 15:28

    I've got Dependency Injection with a really simple example like this.

    See the class below, you'll get the whole idea. As you see unless you supply file it will use the default one settings file, but you can set a settings file and then the class will use it.

    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
    

    Obviously this is the most basic case. In real world you can do the same thing with class types, such as you've got Database Layer and you can switch the underlying database dll by doing dependency injection and you code will work with any database as soon as you can provide the valid class (a class which implements the interface you are using).

    After got the basic you can do this on larger scope and totally independent from the application by using DI frameworks like unity.

    0 讨论(0)
提交回复
热议问题