L'accès ASP.NET Core DI Conteneur De Statique de la Classe Factory
J'ai créé un ASP.NET Core, MVC/WebApi site qui a un RabbitMQ abonné basé sur James Encore l'article du blog de Dans le Monde réel PubSub de Messagerie avec RabbitMQ.
Dans son article, il utilise une classe statique pour démarrer la file d'attente de l'abonné et de définir le gestionnaire d'événement pour en file d'attente des événements. Cette méthode statique instancie ensuite le gestionnaire d'événement par le biais des classes statiques usine de classe.
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text;
namespace NST.Web.MessageProcessing
{
public static class MessageListener
{
private static IConnection _connection;
private static IModel _channel;
public static void Start(string hostName, string userName, string password, int port)
{
var factory = new ConnectionFactory
{
HostName = hostName,
Port = port,
UserName = userName,
Password = password,
VirtualHost = "/",
AutomaticRecoveryEnabled = true,
NetworkRecoveryInterval = TimeSpan.FromSeconds(15)
};
_connection = factory.CreateConnection();
_channel = _connection.CreateModel();
_channel.ExchangeDeclare(exchange: "myExchange", type: "direct", durable: true);
var queueName = "myQueue";
QueueDeclareOk ok = _channel.QueueDeclare(queueName, true, false, false, null);
_channel.QueueBind(queue: queueName, exchange: "myExchange", routingKey: "myRoutingKey");
var consumer = new EventingBasicConsumer(_channel);
consumer.Received += ConsumerOnReceived;
_channel.BasicConsume(queue: queueName, noAck: false, consumer: consumer);
}
public static void Stop()
{
_channel.Close(200, "Goodbye");
_connection.Close();
}
private static void ConsumerOnReceived(object sender, BasicDeliverEventArgs ea)
{
//get the details from the event
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
var messageType = "endpoint"; //hardcoding the message type while we dev...
//instantiate the appropriate handler based on the message type
IMessageProcessor processor = MessageHandlerFactory.Create(messageType);
processor.Process(message);
//Ack the event on the queue
IBasicConsumer consumer = (IBasicConsumer)sender;
consumer.Model.BasicAck(ea.DeliveryTag, false);
}
}
}
Il fonctionne très bien jusqu'au moment où j'ai maintenant besoin de résoudre un service dans mon message du processeur de l'usine plutôt que de simplement écrire dans la console.
using NST.Web.Services;
using System;
namespace NST.Web.MessageProcessing
{
public static class MessageHandlerFactory
{
public static IMessageProcessor Create(string messageType)
{
switch (messageType.ToLower())
{
case "ipset":
//need to resolve IIpSetService here...
IIpSetService ipService = ???????
return new IpSetMessageProcessor(ipService);
case "endpoint":
//need to resolve IEndpointService here...
IEndpointService epService = ???????
//create new message processor
return new EndpointMessageProcessor(epService);
default:
throw new Exception("Unknown message type");
}
}
}
}
Est-il un moyen d'accéder à la ASP.NET de Base conteneur IoC pour résoudre les dépendances? Je n'ai pas vraiment envie de le mettre en rotation l'ensemble de la pile de dépendances à la main 🙁
Ou, est-il une meilleure façon pour vous abonner à RabbitMQ à partir d'un ASP.NET application de Base? J'ai trouvé RestBus mais cela n'a pas été mis à jour pour la Base 1.x
Je suis curieux, n'a les réponses ci-dessous a aidé?
OriginalL'auteur Nick | 2016-11-15
Vous devez vous connecter pour publier un commentaire.
Vous pouvez éviter les classes statiques et utiliser l'Injection de Dépendance tout le chemin à travers combiné avec:
IApplicationLifetime
pour démarrer/arrêter l'auditeur à chaque fois que l'application démarre/s'arrête.IServiceProvider
pour créer des instances du message processeurs.Première chose, nous allons passer à la configuration de sa propre classe, qui peut être rempli à partir de la appsettings.json:
Ensuite, convertir
MessageHandlerFactory
dans une situation de non-statique de la classe qui reçoit unIServiceProvider
comme une dépendance. Il va utiliser le fournisseur de service pour résoudre le message processeur instances:De cette façon, votre message processeur classes peuvent recevoir dans le constructeur de toutes les dépendances dont ils ont besoin (tant que vous configurez dans
Startup.ConfigureServices
). Par exemple, je suis en injectant une ILogger dans un de mes échantillon de processeurs:Maintenant convertir
MessageListener
dans une situation de non-statique de la classe qui dépendIOptions<RabbitOptions>
etMessageHandlerFactory
.Il est très similaire à la votre celui d'origine, j'ai juste remplacé les paramètres de la méthode de Démarrage avec les options de dépendance et le gestionnaire de l'usine est maintenant une dépendance à la place d'une classe statique:Près de là, vous devrez mettre à jour le
Startup.ConfigureServices
méthode de sorte qu'il sait au sujet de vos services et options (Vous pouvez créer des interfaces pour l'écouteur et un gestionnaire d'usine si vous voulez):Enfin, la mise à jour de la
Startup.Configure
méthode de prendre un supplément deIApplicationLifetime
de paramètres et démarrer/arrêter l'auditeur de message dans leApplicationStarted
/ApplicationStopped
événements (Bien que j'ai remarqué il y a quelques problèmes avec la ApplicationStopping événement à l'aide de IISExpress, comme dans cette question):Le haut-DI est relativement simple dans certains aspects comme la gestion de durée de vie. Il pourrait être intéressant d'envisager d'accrocher une 3e partie récipient comme Autofact, StructureMap, Unité, etc dans un cas comme celui-ci et de créer un portée par message, par exemple
Oui, mais si vous avez l'habitude de faire cela et utiliser par défaut, j'espère au moins ne pas obtenir de l'élimination par conteneur?
Vous pourriez faire
using (var scope = services.CreateScope())
puis résoudre des services descope.ServiceProvider
qui sera rendue lorsque le champ est supprimé.Merci pour cette. Je n'ai pas eu le temps de l'essayer, mais j'aimerais obtenir loin de la statique de la mise en œuvre et il semble que ça fait beaucoup de sens.
OriginalL'auteur Daniel J.G.
Même si l'utilisation de l'Injection de Dépendances est une meilleure solution, mais dans certains cas, vous devez utiliser des méthodes statiques (comme dans les Méthodes d'Extension).
Pour ces cas, vous pouvez ajouter une propriété statique de votre statique de la classe et de l'initialiser dans votre ConfigureServices méthode.
Par exemple:
et dans votre ConfigureServices:
OriginalL'auteur HamedH
Voici mon avis sur votre cas:
Si possible, j'aimerais envoyer résolu service en tant que paramètre
Sinon durée de vie en service serait important.
Si le service est un singleton, je voudrais juste mis de la dépendance sur la méthode configure ():
Si la durée de vie est limitée, je voudrais utiliser HttpContextAccessor:
OriginalL'auteur adem caglin