我有一个应用程序侦听队列上的消息并处理所述消息。
到目前为止,我已经为我们的每个客户安装了一个单独的应用程序实例,每个客户在配置文件中都有自己的数据库连接字符串。在更新应用程序时,这变得很痛苦。
现在我正在尝试重构它,以便能够安装一个具有所有必要连接字符串的实例,并将根据一些运行时参数在数据库之间切换 - 例如 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 ,无论我尝试什么,我都会质疑它的线程安全性。
任何帮助表示赞赏。