Estoy usando una biblioteca de clases que otros componentes pueden reutilizar. En esta biblioteca de clase estoy usando la unidad para la inyección de dependencia. Para esta biblioteca de clase, creo un proyecto de prueba. La persona que llama también obtiene un proyecto de prueba. Una cosa de la que no estoy seguro es la ubicación de los enlaces. ¿Debería incorporar esto en la biblioteca de la clase o debería hacer esto desde la aplicación de llamada?IoC en la biblioteca de clases. Dónde arrancar
Respuesta
Este es un problema interesante. ¿Cómo puede la dependencia inyectar ensambles reutilizables que no tienen un punto de entrada? Realmente me gustaría ver la respuesta de otras personas.
Dependency injection es responsabilidad del entry-point assembly. Sin embargo, si tiene muchas clases y ensamblajes que necesitan DI, entonces es posible que se queden fuera de algunas clases/ensamblajes y la tarea sea onerosa.
Solución Uno
Uso de la convención sobre la configuración. Se apega a una regla de la clase Foo
implementando IFoo
, etc. Muchos frameworks DI tienen los medios para configurarlo usando la convención.
solución de dos
encima solución no resuelve todos los problemas, ya que a veces es necesario parametrizar la configuración de la inyección. Aquí es cómo han resuelto el problema (especialmente para aquellos conjuntos cargados por MEF y esto es para AutoFac
):
creado una interfaz IIocInstaller
donde (se pasa o constructor) contenedor
public interface IIocInstaller
{
void Setup(ContainerBuilder builder);
}
creado un atributo de ensamblado que las banderas montajes que requieren DI:
[AttributeUsage(AttributeTargets.Assembly)]
public class ExportAssemblyAttribute : Attribute
{
}
En cada conjunto, I crear una clase que establece DI:
[assembly: ExportAssembly]
namespace This.That
{
[Export(typeof(IIocInstaller))]
public class IocInstaller : IIocInstaller
{
public void Setup(ContainerBuilder builder)
{
....
}
}
}
Luego, en el punto de entrada, tengo un código común que mira a través de todos los conjuntos cargados (incluyendo los MEFed) que tienen el atributo de montaje y luego busque el tipo que implementa el IIocInstaller
y luego llame al programa de instalación en ellos.
Gracias por la sugerencia. Me sacó de mi patrón de pensamiento. Ahora estamos presentando un proyecto de configuración separado. De esta forma, la biblioteca de clases puede usar diferentes implementaciones. – Patrick
@Patrick es un problema difícil. Los constructores estáticos no necesariamente funcionan ya que podría ser tarde para DI, especialmente para contenedores de dos pasos como AutoFac. – Aliostad
Primero, esta es una respuesta automática a una pregunta de Unity. Además, tener una biblioteca compatible con múltiples contenedores IoC/DI no debería ser difícil si los contenedores admiten las extensiones conceptuales de forma similar a Unity. Simplemente tendría una clase de extensiones dedicada que utiliza el contenedor del implementador de IoC/DI y luego la aplicación de punto de entrada puede elegir la extensión que coincida con su elección de IoC/DI. –
Hacerlo desde la aplicación de llamada supone más carga para la aplicación de llamada. Dejando la oportunidad de omitir la inicialización y meterse en problemas.
Lo haría en la biblioteca de clases, por ejemplo, en un constructor estático.
Esa no es una buena elección. La aplicación de punto de entrada debe poseer y controlar el contenedor, por lo que la unidad permite registrar extensiones y la clase base UnityContainerExtension para facilitar la implementación de la interfaz IUnityContainerExtensionConfigurator. Ver mi respuesta para un ejemplo. –
Sé que se ha elegido una respuesta, sin embargo, creo que una parte de Unity se está pasando por alto. Dado que esta era una pregunta específica de Unity, pensé en señalar la clase base UnityContainerExtension que implementa IUnityContainerExtensionConfigurator. Esto está ahí para que la biblioteca de API se extienda para facilitar que la aplicación de punto de entrada propietaria del contenedor tenga una manera fácil de asegurarse de que su biblioteca se registre correctamente en el contenedor, y le permite al propietario de API controlar lo que se registra y cómo.
Esto es utilizado por las Microsoft Enterprise Libraries para este propósito.
Voy a utilizar una biblioteca de registro como un simple:
public class LoggingUnityExtension : UnityContainerExtension
{
protected override void Initialize()
{
Container.RegisterType<ILogger, Logger>(new ContainerControlledLifetimeManager());
}
}
A continuación, la aplicación de punto de entrada hace esto:
public class Bootstrapper : UnityBootstrapper
{
protected override void ConfigureContainer()
{
base.ConfigureContainer();
Container.AddNewExtension<EnterpriseLibraryCoreExtension>();
Container.AddNewExtension<LoggingUnityExtension>();
// ...
}
// ...
}
Ahora se han registrado Enterprise Library y la API para el Biblioteca de registro. Es muy simple para la aplicación de punto de entrada con este método, que es lo que cualquier desarrollador de biblioteca debe tener como objetivo.
Podría querer hacer referencia a la biblioteca para que la gente pueda usar su ejemplo fácilmente. ¿Necesita la 'EnterpriseLibraryCoreExtension' para que esto funcione? – ajbeaven
Eso depende de sus necesidades, pero generalmente cuando usa Unity y cualquiera de los Bloques EntLib necesitará usarlo casi siempre. Recuerde que estos son fragmentos de código para mostrar ejemplos que no son completamente funcionales. Sí afirmo en mis comentarios que estoy usando bibliotecas de Microsoft Enterprise que deberían ser suficientes para el ejemplo. En cuanto a ILogger y Logger, se usan solo para mostrar cómo usar una extensión de contenedor para no mostrarle cómo crear un Logger. Esa implementación no es relevante. –
O.K Cree una biblioteca llamada Project.Ioc. Instalar Unity aquí. Haga referencia a las otras capas a la biblioteca Ioc. Y Biblioteca Ioc a la capa de presentación. Crea una clase llamada UnityHelper.
/// <summary>
/// Bind the given interface in request scope
/// </summary>
public static class IocExtensions
{
public static void BindInRequestScope<T1, T2>(this IUnityContainer container) where T2 : T1
{
container.RegisterType<T1, T2>(new HierarchicalLifetimeManager());
}
public static void BindInSingletonScope<T1, T2>(this IUnityContainer container) where T2 : T1
{
container.RegisterType<T1, T2>(new ContainerControlledLifetimeManager());
}
}
/// <summary>
/// The injection for Unity
/// </summary>
public static class UnityHelper
{
public static IUnityContainer Start()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new Unity.Mvc4.UnityDependencyResolver(container));
return container;
}
/// <summary>
/// Inject
/// </summary>
/// <returns></returns>
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// Database context, one per request, ensure it is disposed
container.BindInRequestScope<IMVCForumContext, MVCForumContext>();
container.BindInRequestScope<IUnitOfWorkManager, UnitOfWorkManager>();
//Bind the various domain model services and repositories that e.g. our controllers require
container.BindInRequestScope<ITopicService, TopicService>();
container.BindInRequestScope<ITopicTagRepository, TopicTagRepository>();
//container.BindInRequestScope<ISessionHelper, SessionHelper>();
return container;
}
}
Eche un vistazo al proyecto MvcForum. Hay una biblioteca de clases MvcForm.Ioc. La biblioteca obtiene otras referencias de Layer. Solo hay una clase llamada UnityHelper.
https://github.com/leen3o/mvcforum
espero que esto es wat que busca.
- 1. Contenedor IoC para bibliotecas de clases portátiles
- 2. IoC, ¿dónde colocas el contenedor?
- 3. Biblioteca IoC compatible con MonoTouch?
- 4. IoC y ASP.NET MVC, ¿dónde comienza todo?
- 5. Cómo arrancar desde la línea de comandos
- 6. ¿Dónde poner clases internas?
- 7. ¿Dónde está la biblioteca COM de Bonjour?
- 8. Dónde obtener clases com.sun.j3d
- 9. ¿Cómo debo diseñar una biblioteca de clases para permitir IoC, pero no depender de un contenedor en particular?
- 10. ¿Qué es una biblioteca de clases portátil?
- 11. Recursos globales en una biblioteca de clases
- 12. Obtención del despachador de IU en la biblioteca de clases
- 13. Agregar referencia de System.Web.Script en la biblioteca de clases
- 14. ¿Sincronización en clases de biblioteca/terceros?
- 15. Registro en toda la biblioteca de clases sin referencias pasa
- 16. Codificación Html en la biblioteca de clases .NET
- 17. Generar Hash SHA1 en la Biblioteca de clases portátil
- 18. ¿Cuál es la diferencia entre arrancar y recolectar en Rails?
- 19. C# biblioteca de clases de localización
- 20. ¿Diferencias entre la Biblioteca de control personalizado de WPF y la Biblioteca de clases simple?
- 21. Creación de kernel Ninject dentro de una biblioteca de clases
- 22. sbt: Agregue dependencia en la biblioteca Scalatest. ¿Dónde?
- 23. ¿Dónde está la biblioteca C estándar en Mac OS X?
- 24. Uso de Async CTP con la Biblioteca de clases portátil
- 25. Biblioteca de clases portátil y .NET ConcurrentDictionary
- 26. rieles retardada de empleo y la biblioteca de clases
- 27. Biblioteca de clases portátil equivalente a MethodBase.GetCurrentMethod
- 28. Código fuente para las clases de biblioteca Java
- 29. Inyección de dependencias en clases de modelo de dominio con Nhibernate (ASP.NET MVC + IOC)
- 30. Inyección de dependencias en AuthorizeAttribute en una biblioteca de clases
Puede echar un vistazo a [Enterprise Library de p & p] (http://entlib.codeplex.com). Están usando Unity debajo de las fundas y el contenedor se inicializa sin interacción del usuario. –
@Sebastian, eso no es del todo cierto, la aplicación de punto de entrada (también conocido como el usuario) tiene que inicializar un contenedor y registrar la extensión de unidad de biblioteca de empresa. Vea mi respuesta para un ejemplo de esto a continuación. –