Hi in Autofac I am abble to do this:
public class Service1_Client
{
private const string ServiceName = "Service1";
Func<string, RabitMqClient> _clientFunc;
public Service1_Client(Func<string, RabitMqClient> clientFunc)
{
_clientFunc = clientFunc;
}
public IList<object> GetData()
{
return _clientFunc(this.ServiceName).Get<IList<object>>();
}
}
public class Service2_Client
{
private const string ServiceName = "Service2";
Func<string, RabitMqClient> _clientFunc;
public Service2_Client(Func<string, RabitMqClient> clientFunc)
{
_clientFunc = clientFunc;
}
public IList<object> GetData()
{
return _clientFunc(this.ServiceName).Get<IList<object>>();
}
}
public class RabitMqClient
{
private IConnectionFactory _connectionFactory;
private string _baseServiceName;
public RabitMqClient(IConnectionFactory connectionFactory, string baseServiceName)
{
_connectionFactory = connectionFactory;
_baseServiceName = baseServiceName;
}
public TResult Get<TResult>()
{
string topicName = this.GetTopicName();
///Connect to the channel that uses the topic and ask for data...
}
private string GetTopicNAme()
{
/// this should be an algoritam for getting the topic from the speccified baseServiceName (I have omitted the details)
return this._baseServiceName;
}
}
Now the explanation: Basically I have a class (RabitMqClient) that depends on 2 parameters:
Those parameters are used to connect to the RabbitMq server. Now I use Topics in RabbitMq to diversify services, and to get the correct Topic, the string parameter baseServiceName is used. It is expected the caller (Service1_Client, Service2_Client) to supply the string parameter baseServiceName.
In Autofac I can register this class like this:
builder.Register((context, parameters) =>
{
var param = parameters.First() as Autofac.TypedParameter;
return new HcRabbitMqClient(
context.Resolve<IConnectionFactory>(),param.Value.ToString());
}).AsSelf().InstancePerDependency();
This tells Autofac, that when requesting this class, let the Autofac resolve the first parameter but the Caller will supply the second (string) parameter at the call site. This string parameter will then be put in the parameters value. The usage of this can be seen in the code above (Service1_Client, Service2_Client) GetData() methods;
How to do this in StructureMap?
答案 0 :(得分:1)
试试这个
For<Func<string, RabitMqClient>>().Use(cstr => new RabitMqClient(cstr));
答案 1 :(得分:1)
扩展工厂模式怎么样?
public interface IRabitMqClientFactory
{
IRabitMqClientFactory Create(string baseServiceName);
}
public class RabitMqClientFactory : IRabitMqClientFactory
{
public RabitMqClientFactory(IConnectionFactory connectionFactory){
_connectionFactory = connectionFactory;
}
public IRabitMqClientFactory Create(string baseServiceName)
{
_baseServiceName = baseServiceName;
}
}
然后简单
public class Service1_Client
{
private const string ServiceName = "Service1";
private RabbitMqClient _rabbitMqClient;
public Service1_Client(IRabitMqClientFactory rabitMqClientFactory)
{
_rabbitMqClient = rabitMqClientFactory.Create(ServiceName);
}
public IList<object> GetData()
{
return _rabbitMqClient.Get<IList<object>>();
}
}
它比IoC中的复杂逻辑更具可读性。