У меня есть приложение, которое прослушивает сообщения в очереди и обрабатывает указанные сообщения.Переключение баз данных с использованием DI/StructureMap
До сих пор у меня был отдельный экземпляр приложения, установленный для каждого из наших клиентов, каждый со своими строками подключения базы данных в файле конфигурации. Это становится болью, когда дело доходит до обновления приложения.
Теперь я пытаюсь реорганизовать это, поэтому я могу установить один экземпляр, который имеет все необходимые строки подключения, и будет переключаться между базами данных в зависимости от некоторого параметра времени выполнения - message.Client например.
Это все хорошо, если я телеграфировать все вручную ....
var data = new MyData(message.Client);
var processor = new MessageProcessor(new Foo(data), new Bar(data));
processor.Process(message);
... но я изо всех сил, чтобы получить мою голову вокруг, как я даже начать, чтобы достичь этого, используя DI контейнер.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using StructureMap;
namespace M.Test
{
public interface IData
{
IEnumerable<string> Names { get; }
}
public class MyData : IData
{
private readonly string _client;
public MyData(string client)
{
_client = client;
}
public IEnumerable<string> Names
{
get { return _client == "Client A" ? new[] {"One", "Two", "Three"} : new[] {"Uno", "Dos", "Tres"}; }
}
}
public interface IFoo
{
void FooDo();
}
public class Foo : IFoo
{
private readonly IData _dataContext;
public Foo(IData dataContext)
{
_dataContext = dataContext;
}
public void FooDo()
{
Debug.WriteLine(_dataContext.Names.First());
}
}
public interface IBar
{
void BarDo();
}
public class Bar : IBar
{
private readonly IData _data;
public Bar(IData data)
{
_data = data;
}
public void BarDo()
{
Debug.WriteLine(_data.Names.Last());
}
}
public interface IMessageProcessor
{
void Process(Message message);
}
public class MessageProcessor : IMessageProcessor
{
private readonly IFoo _foo;
private readonly IBar _bar;
public MessageProcessor(IFoo foo, IBar bar)
{
_foo = foo;
_bar = bar;
}
public void Process(Message message)
{
_foo.FooDo();
_bar.BarDo();
}
}
public class Message
{
public string Client { get; set; }
}
class Program
{
private static Container _container;
static void Main(string[] args)
{
_container = new Container();
_container.Configure(x =>
{
x.For<IData>().Use<MyData>();
x.For<IMessageProcessor>().Use<MessageProcessor>();
x.For<IBar>().Use<Bar>();
x.For<IFoo>().Use<Foo>();
});
MessageReceived(new Message {Client = "Client A"});
MessageReceived(new Message {Client = "Client B"});
MessageReceived(new Message {Client = "Client A"});
Console.ReadKey();
}
private static void MessageReceived(Message message)
{
// Fine if I do this...
var data = new MyData(message.Client);
var processor = new MessageProcessor(new Foo(data), new Bar(data));
processor.Process(message);
// But would like to do this...
var diProcessor = _container.TryGetInstance<IMessageProcessor>();
diProcessor.Process(message);
}
}
}
Из того, что я прочитал, я вижу, что параметры конструктора могут использоваться с StructureMap. Например:
x.For<IData>().Use<MyData>().Ctor<string>("client").Is(someValueAtRunTime);
... но не могу понять, когда/как someValueAtRunTime должен быть установлен, и все, что я пытаюсь я вопрос, как поточно это.
Любая помощь приветствуется.