c# servicestack inversion-of-control ioc-container funq

c# - Cómo registrar múltiples instancias de IDbConnectionFactory usando Funq en ServiceStack.net



inversion-of-control ioc-container (4)

¿Cómo haría para registrar diferentes instancias de IDbConnectionFactory en Funq y luego acceder a ellas directamente dentro de sus servicios? ¿Las instancias nombradas de alguna manera entran en juego aquí?

¿Es este el mejor enfoque a tomar cuando se usan diferentes bases de datos en todos los servicios?

¡Gracias!

EDITAR:

Un ejemplo ;). Podría estar muy lejos de aquí porque soy bastante nuevo en IoC, pero digamos que tengo 2 conexiones de base de datos separadas que me gustaría insertar. En ServiceStack, esto se hace en Global.asax.

container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(@"Connection String 1", SqlServerOrmLiteDialectProvider.Instance)); container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(@"Connection String 2", SqlServerOrmLiteDialectProvider.Instance));

Ambos parecen ser inyectados honky dory.

Luego se accede a estos automáticamente en el extremo del servicio a través de algo como esto:

public IDbConnectionFactory DbFactory { get; set; }

En este caso, parece que me está dando el primero registrado. ¿Cómo puedo obtener acceso a uno específico en el extremo del servicio? Esperemos que eso lo haga un poco más claro.

Aquí hay un ejemplo completo de ServiceStack.Examples que solo usa 1 IDbConnectionFactory: Movies Rest


Aunque Funq no admite el cableado automático, la implementación de ServiceStack sí lo hace. La última versión de ServiceStack incluye las sobrecargas de Funq.Container:

container.RegisterAutoWired<T>(); container.RegisterAutoWiredAs<T,TAs>(); container.RegisterAs<T,TAs>();

Así que en el ejemplo de Steven también puedes hacer:

container.RegisterAs<YellowDbConnectionFactory,IYellowDbConnectionFactory>();

Y registrará automáticamente las dependencias para usted.


Intente usar el patrón Repositorio en lugar de este IoC (lo que complica las cosas innecesariamente). El código de arriba parece no funcionar. Sospecha que algo ha cambiado. Todavía no estoy seguro de cómo registrar una IDbConnectionFactory llena mágicamente la propiedad IDbConnection. Me encantaría alguna explicación sobre esto. Si alguna vez alguien consigue que esto funcione con el contenedor ServiceStack IoC ... entonces me encantaría ver cómo. Y sería enormemente beneficioso actualizar los documentos de la SS (estoy muy feliz de hacerlo)


Mi pregunta anterior sigue siendo válida, pero lo siguiente podría ayudarte de todos modos.

Funq no admite la inyección automática de constructores (también conocido como cableado automático), y tendrá que hacerlo a mano mediante la construcción de expresiones lambda Func<T> . Debido a que ya está realizando la inyección del constructor a mano, es fácil elegir qué IDbConnectionFactory desea inyectar en sus servicios. Ejemplo:

IDbConnectionFactory yellowDbConFactory = new YellowDbConnectionFactory(); IDbConnectionFactory blueDbConFactory = new BlueDbConnectionFactory(); IDbConnectionFactory purpleDbConFactory = new PurpleDbConnectionFactory(); container.Register<IService1>(c => new Service1Impl(yellowDbConFactory, c.Resolve<IDep1>()); container.Register<IService2>(c => new Service2Impl(blueDbConFactory); container.Register<IService3>(c => new Service3Impl(purpleDbConFactory, c.Resolve<IDep2>());

Por supuesto, también puede utilizar registros con nombre, como este:

container.Register<IDbConnectionFactory>("yellow", new YellowDbConnectionFactory()); container.Register<IDbConnectionFactory>("blue", new BlueDbConnectionFactory()); container.Register<IDbConnectionFactory>("purple", new PurpleDbConnectionFactory()); container.Register<IService1>(c => new Service1Impl( c.Resolve<IDbConnectionFactory>("yellow"), c.Resolve<IDep1>()); container.Register<IService2>(c => new Service2Impl( c.Resolve<IDbConnectionFactory>("blue")); container.Register<IService3>(c => new Service3Impl( c.Resolve<IDbConnectionFactory>("purple"), c.Resolve<IDep2>());

Debido a la falta de soporte para el cableado automático, terminarás con estos registros bastante complicados, y esto pronto resultará en una pesadilla de mantenimiento de la raíz de tu composición, pero eso no está relacionado con tu pregunta ;-)

Por lo general, debe intentar evitar la ambigüedad en su registro. En su caso, tiene una sola interfaz, que hace dos cosas (se conecta a dos bases de datos). A menos que ambas bases de datos compartan exactamente el mismo modelo, cada base de datos merece su propia interfaz (si las dos implementaciones no son intercambiables, estará violando el principio de sustitución de Liskov ):

interface IYellowDbConnectionFactory : IDbConnectionFactory { } interface IPurpleDbConnectionFactory : IDbConnectionFactory { }

Debido a la forma en que funciona ServiceStack, es probable que necesite implementar una implementación para cada uno:

class YellowDbConnectionFactory : OrmLiteConnectionFactory, IYellowDbConnectionFactory { public YellowDbConnectionFactory(string s) : base(s){} } class PurpleDbConnectionFactory : OrmLiteConnectionFactory, IPurpleDbConnectionFactory { public YellowDbConnectionFactory(string s) : base(s){} }

Ahora debe cambiar la definición de sus servicios para usar la interfaz específica en lugar de usar IDbConnectionFactory :

public class MovieService : RestServiceBase<Movie> { private readonly IYellowDbConnectionFactory dbFactory; public MovieService(IYellowDbConnectionFactory factory) { this.dbFactory = factory; } }

Tenga en cuenta que esta clase ahora usa inyección de constructor en lugar de inyección de propiedad. Puede hacer que esto funcione con la inyección de propiedades, pero generalmente es mejor ir con la inyección de constructor. Aquí hay una pregunta SO sobre esto.

Con Funq, tu configuración se verá así:

container.Register<MovieService>(c => new MovieService( c.Resolve<IYellowDbConnectionFactory>());

Esas dos nuevas interfaces y dos clases y el cambio a MovieService no le ganaron mucho, porque Funq no admite el cableado automático. Usted será el que está cableando todo juntos manualmente. Sin embargo, cuando se cambia a un marco que admite el cableado automático, este diseño permite que el contenedor inyecte las dependencias correctas sin problemas, porque no hay discusión sobre qué inyectar.


Pensé que iba a meter mis 2 centavos aquí, aunque me doy cuenta de que la pregunta es bastante antigua. Quería acceder a una base de datos transaccional y una base de datos de registro desde ServiceStack y así es como terminé haciéndolo desde el método de configuración de AppHostBase ():

container.Register<IDbConnectionFactory>( c => { OrmLiteConnectionFactory dbFactory = new OrmLiteConnectionFactory(ConfigurationManager.ConnectionStrings["MyTransactionalDB"].ConnectionString, MySqlDialect.Provider); dbFactory.ConnectionFilter = x => new ProfiledDbConnection(x, Profiler.Current); dbFactory.RegisterConnection("LoggingDB", ConfigurationManager.ConnectionStrings["MyLoggingDB"].ConnectionString, MySqlDialect.Provider); return dbFactory; });

De forma predeterminada, se utiliza "MyTransactionalDB" cuando se abre una conexión desde la fábrica, pero puedo acceder explícitamente a la base de datos de registro desde un servicio a través de:

using (var db = DbFactory.Open("LoggingDB")) { db.Save(...); }