inyeccion - ¿Inyección de dependencia en.NET con ejemplos?
inyeccion de dependencias c# framework (8)
¿Puede alguien explicar la inyección de dependencia con un ejemplo básico de .NET y proporcionar algunos enlaces a recursos de .NET para ampliar el tema?
Esto no es un duplicado de ¿Qué es la inyección de dependencia? porque estoy preguntando sobre ejemplos y recursos específicos de .NET.
Agregue el proyecto de lógica de negocio de la biblioteca de clases de tipo y agregue el código siguiente en él. clase pública UserDetailLogic: IUserDetailLogic {private IUserData _userData = null;
public UserDetailLogic(IUserData userData)
{
_userData = userData;
}
public string getUserDetails()
{
return _userData.getUserDetails();
}
}
public interface IUserDetailLogic
{
string getUserDetails();
}
En su proyecto principal, agregue el código siguiente en el controlador del hogar.
public class HomeController: Controller {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();
}
}
Aquí hay un ejemplo común. Debes iniciar sesión en tu aplicación. Pero, en el momento del diseño, no está seguro de si el cliente desea iniciar sesión en una base de datos, archivos o el registro de eventos.
Entonces, quiere usar DI para diferir esa elección a una que pueda ser configurada por el cliente.
Este es un pseudocódigo (basado aproximadamente en la Unidad):
Usted crea una interfaz de registro:
public interface ILog
{
void Log(string text);
}
luego usa esta interfaz en tus clases
public class SomeClass
{
[Dependency]
public ILog Log {get;set;}
}
inyectar esas dependencias en tiempo de ejecución
public class SomeClassFactory
{
public SomeClass Create()
{
var result = new SomeClass();
DependencyInjector.Inject(result);
return result;
}
}
y la instancia está configurada en 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>
Ahora, si desea cambiar el tipo de registrador, ingrese a la configuración y especifique otro tipo.
Básicamente pasas todos los objetos necesarios en el constructor. Alternativamente, puede resolverlos en tiempo de ejecución usando una resolución de interfaz (aunque esto es menos seguro). Puede encontrar excelentes ejemplos en el sitio web de Ninject para el primer enfoque, y buenos ejemplos en el sitio web de Unity para el segundo enfoque. Esto evita la necesidad de singletons y le permite colocar fácilmente un objeto de reemplazo que se ajuste a la interfaz deseada
Cree un proyecto de capa de BD (biblioteca de clases) y agregue el código siguiente en él.
public class UserData : IUserData
{
public string getUserDetails()
{
return "Asif";
}
}
public interface IUserData
{
string getUserDetails();
}
Creo que es importante que primero aprenda DI sin IoC Containers. Por lo tanto, he escrito un ejemplo que lentamente se convierte en un Contenedor de IoC. Es un ejemplo real de mi trabajo, pero todavía lo suficientemente básico como para que los principiantes capten la esencia de DI. Puede encontrarlo aquí: https://dannyvanderkraan.wordpress.com/2015/06/15/real-world-example-of-dependeny-injection/
Está en C # .NET y luego usa Unity.
Actualización después del comentario:
Sección relevante del artículo
"Observe los siguientes cambios en el diseño original:
Fuimos por el patrón "Constructor Injection" para implementar DI y los pasos de refactorización fueron:
- Resuma la interfaz de CardPresenceChecker creando la interfaz ICardPresenceChecker;
- Haga explícito que este CardPresenceChecker solo funciona para la biblioteca de la Compañía X, cambiando su nombre a XCardPresenceChecker;
- Haga que XCardPresenceChecker implemente la interfaz ICardPresenceChecker;
- Resuma la propiedad de LogInService para ser del tipo ICardPresenceChecker en lugar de ''saber'' exactamente qué implementación se lleva a bordo;
- Y por último pero no menos importante, demanda de los usuarios (otros desarrolladores) de LogInService que proporcionen cualquier clase que al menos implemente ICardPresenceChecker para que LogInService pueda hacer su trabajo.
El constructor de LogInService se ve así:
this.myCardPresenceChecker = cardPresenceChecker;
this.myCardPresenceChecker.CardIn += MyCardPresenceChecker_CardIn;
this.myCardPresenceChecker.CardOut += MyCardPresenceChecker_CardOut;
this.myCardPresenceChecker.Init();
Entonces, ¿dónde proporciona LogInService con una implementación de ICardPresenceChecker? Por lo general, desea este ''mapeo'' (en este ejemplo, ''asignaremos'' ICardPresenceChecker a XCardPresenceChecker) en un lugar central al inicio de una aplicación, conocida conceptualmente como la '''' Raíz de composición ''''. Para una vieja aplicación de consola normal que podría ser el vacío principal en la clase de programa. Entonces, para este ejemplo, este fragmento de código se usaría en el lugar mencionado anteriormente:
LogInService logInService = new LogInService (nuevo XCardPresenceChecker ()); "
Instale los paquetes de Nuget debajo en el nombre del proyecto mvc4 principal SampleDependency. Unity Web Hosting Unity.mvc4, unity.webapi y MicrosoftAsp.Net Web API 2.2
En proyecto 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
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<IUserDetailLogic, UserDetailLogic>();
container.RegisterType<IUserData, UserData>();
RegisterTypes(container);
return container;
}
public static void RegisterTypes(IUnityContainer container)
{
}
}
Tengo Dependency Injection con un ejemplo realmente simple como este.
Vea la clase a continuación, obtendrá la idea completa. Como ve, a menos que suministre el archivo, usará el archivo predeterminado de configuración, pero puede establecer un archivo de configuración y luego la clase lo usará.
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
Obviamente este es el caso más básico. En el mundo real, puede hacer lo mismo con los tipos de clase, como la Capa de base de datos y puede cambiar la base de datos subyacente haciendo inyección de dependencia y su código funcionará con cualquier base de datos tan pronto como pueda proporcionar la clase válida. (una clase que implementa la interfaz que está utilizando).
Después de obtener lo básico, puede hacerlo en un ámbito más amplio y totalmente independiente de la aplicación utilizando marcos DI como unity.
Ninject debe tener una de las muestras más Ninject : (reconstruido a partir de la muestra)
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");
}
}
Esto, para mí, lee con mucha fluidez, antes de que comiences tu dojo puedes decidir cómo armar a tus Samurais.