Подтвердить что ты не робот

Инъекция зависимостей в .NET с примерами?

Может ли кто-нибудь объяснить инъекцию зависимостей с базовым примером .NET и предоставить несколько ссылок на ресурсы .NET для расширения темы?

Это не дубликат Что такое инъекция зависимостей?, потому что я спрашиваю о конкретных примерах и ресурсах .NET.

4b9b3361

Ответ 1

Вот общий пример. Вам нужно войти в свое приложение. Но во время разработки вы не уверены, хочет ли клиент регистрироваться в базе данных, файлах или журнале событий.

Итак, вы хотите использовать DI, чтобы отложить этот выбор до того, который может быть настроен клиентом.

Это некоторый псевдокод (примерно на основе Unity):

Вы создаете интерфейс ведения журнала:

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:

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

Теперь, если вы хотите изменить тип регистратора, просто перейдите в конфигурацию и укажите другой тип.

Ответ 2

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

Это, для меня, читается очень плавно, прежде чем вы начнете свой dojo, вы можете решить, как вооружить самураев.

Ответ 3

Я думаю, что важно, чтобы вы впервые изучили DI без контейнеров IoC. Поэтому я написал пример, который медленно строится до контейнера IoC. Это реальный пример из моей работы, но все же сделал достаточно базовым для новичков, чтобы схватить сущность DI. Вы можете найти его здесь: https://dannyvanderkraan.wordpress.com/2015/06/15/real-world-example-of-dependeny-injection/

Он в С#.NET, а затем использует Unity.

Обновление после комментария:

Соответствующий раздел статьи

"Соблюдайте следующие изменения оригинальной конструкции:

быстрый график ситуации

Мы пошли для шаблона "Конструктор инъекции" для реализации DI, а шаги рефакторинга:

  • Аннотация интерфейса CardPresenceChecker путем создания интерфейса ICardPresenceChecker;
  • Укажите, что этот CardPresenceChecker работает только для библиотеки компании X, изменив ее имя на XCardPresenceChecker;
  • Попросите XCardPresenceChecker реализовать интерфейс ICardPresenceChecker;
  • Аннотация свойство LogInService иметь тип ICardPresenceChecker вместо того, чтобы "точно знать, какие осуществление осуществляется на борту;
  • И последнее, но не менее важное: требовать от пользователей (других разработчиков) LogInService, чтобы они предоставляли какой-либо класс, который хотя бы реализует ICardPresenceChecker, чтобы LogInService мог выполнить свою задачу.

Конструктор LogInServices выглядит следующим образом:

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

Итак, где вы предоставляете LogInService с внедрением ICardPresenceChecker? Обычно вам нужно это "сопоставление" (в этом примере мы будем отображать ICardPresenceChecker на XCardPresenceChecker) в одном центральном месте при запуске приложения, которое концептуально известно как "Корень композиции". Для обычного консольного приложения, которое может быть void Main в классе Program. Поэтому для этого примера этот фрагмент кода будет использоваться в вышеупомянутом месте:

LogInService logInService = новый LogInService (новый XCardPresenceChecker());

Ответ 4

У меня есть Injection Dependency с действительно простым примером.

Посмотрите класс ниже, вы получите всю идею. Как вы видите, если вы не предоставите файл, он будет использовать файл настроек по умолчанию, но вы можете установить файл настроек, а затем класс будет использовать его.

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

Очевидно, что это самый простой случай. В реальном мире вы можете делать то же самое с типами классов, например, у вас есть уровень базы данных, и вы можете переключить базовую базу данных dll, выполнив инъекцию зависимостей, и код будет работать с любой базой данных, как только вы сможете предоставить действительный класс (класс, который реализует интерфейс, который вы используете).

После получения основного вы можете сделать это в большей области и полностью независимы от приложения, используя фреймы DI, такие как единство.

Ответ 5

Вы по существу передаете все необходимые объекты в конструкторе. Кроме того, вы можете разрешить их во время выполнения с помощью распознавателя интерфейса (хотя это менее типично). Вы можете найти отличные примеры на веб-сайте Ninject для первого подхода, а также хорошие примеры на веб-сайте Unity для второго подхода. Это позволяет избежать необходимости в одиночных играх и позволяет легко сбрасывать заменяемый объект, соответствующий желаемому интерфейсу.

Ответ 6

Установите ниже пакеты Nuget в главном проекте проекта mvc4 SampleDependency. Unity.mvc4, unity.webapi и веб-интерфейс MicrosoftAsp.Net Web 2.2.

В веб-проекте

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)
    {

    }
}

Ответ 7

Создайте проект уровня БД (библиотеку классов) и добавьте в него код ниже.

public class UserData : IUserData
{
    public string getUserDetails()
    {
        return "Asif";
    }
}

public interface IUserData
{
    string getUserDetails();
}

Ответ 8

Добавьте проект логики бизнес-класса библиотеки классов классов и добавьте в него код ниже. Открытый класс UserDetailLogic: IUserDetailLogic   {       private IUserData _userData = null;

    public UserDetailLogic(IUserData userData)
    {
        _userData = userData;
    }
    public string getUserDetails()
    {
        return _userData.getUserDetails();
    }
}

public interface IUserDetailLogic
{
    string getUserDetails();
}

В вашем основном проекте добавьте код ниже в домашний контроллер.

public class HomeController: контроллер   {       private readonly 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();
    }
}