创建一个新的 ContainerBuilder 实例是一种好的做法吗?
Is it a good practice to create a new instance of ContainerBuilder?
下面的示例代码基本上是调用了多个dummy服务,然后合并结果。 (在实际应用中,它们将是网络服务。)
问题: 创建一个新的 ContainerBuilder 实例是个好习惯吗?请在 Main 方法中查看几个 *****。
如果没有,你能给我指明正确的方向吗?我愿意接受任何建议。
注意: Build() 或 Update() 方法只能在 ContainerBuilder 上调用一次。
输出
主要
private static void Main(string[] args)
{
var builder = new ContainerBuilder();
var container = builder.Build();
// ***** Create a new instance of ContainerBuilder *****
builder = new ContainerBuilder();
builder.RegisterType<AlfaService>().As<IService>().Named<IService>("a");
builder.RegisterType<BravoService>().As<IService>().Named<IService>("b");
builder.Update(container);
// ***** Create a new instance of ContainerBuilder *****
builder = new ContainerBuilder();
var services = new Dictionary<string, IService>
{
{"a", container.ResolveNamed<IService>("a")},
{"b", container.ResolveNamed<IService>("b")}
};
builder.RegisterType<CompositeService>().As<ICompositeService>()
.WithParameter("services", services);
builder.Update(container);
// The following is for testing purpose only.
// In real application, I'll inject ICompositeService to MVC controller.
using (ILifetimeScope scope = container.BeginLifetimeScope())
{
IList<int> ids = scope.Resolve<ICompositeService>().GetIdsBySource("a");
Console.WriteLine("AlfaService: " + string.Join(", ", ids));
ids = scope.Resolve<ICompositeService>().GetAllIds();
Console.WriteLine("All Services: " + string.Join(", ", ids));
}
Console.ReadLine();
}
接口
public interface ICompositeService
{
IList<int> GetIdsBySource(string source);
IList<int> GetAllIds();
}
public interface IService
{
IList<int> GetIds();
}
服务
public class CompositeService : ICompositeService
{
private readonly Dictionary<string, IService> _services;
public CompositeService(Dictionary<string, IService> services)
{
_services = services;
}
public IList<int> GetIdsBySource(string source)
{
return _services.Where(x => x.Key == source)
.Select(x => x.Value).First().GetIds();
}
public IList<int> GetAllIds()
{
return _services.SelectMany(x => x.Value.GetIds()).ToList();
}
}
public class AlfaService : IService
{
public IList<int> GetIds() { return new List<int> {1, 2, 3}; }
}
public class BravoService : IService
{
public IList<int> GetIds() { return new List<int> {4, 5, 6}; }
}
要解决参数中的问题,您不必构建容器。构建容器需要时间,应尽可能避免。
解决参数内部问题的最简单方法是使用 WithParameter
方法,如下所示:
builder.RegisterType<CompositeService>()
.As<ICompositeService>()
.WithParameter((pi, c) => pi.Name == "services", (pi, c) =>
{
return new Dictionary<string, IService> {
{ "a", c.ResolveNamed<IService>("a") },
{ "b", c.ResolveNamed<IService>("b") }
};
});
另一种解决方案是创建您自己的 Parameter
public class ServiceParameter : Parameter
{
public override Boolean CanSupplyValue(ParameterInfo pi,
IComponentContext context, out Func<Object> valueProvider)
{
valueProvider = null;
if (pi.Name == "services"
&& pi.ParameterType == typeof(Dictionary<String, IService>))
{
valueProvider = () =>
{
return new Dictionary<string, IService> {
{ "a", context.ResolveNamed<IService>("a") },
{ "b", context.ResolveNamed<IService>("b") }
};
};
}
return valueProvider != null;
}
}
并以这种方式注册:
builder.RegisterType<CompositeService>()
.As<ICompositeService>()
.WithParameter(new ServiceParameter());
在您的情况下,您可能想要使用 Metadata
而不是 命名服务
builder.RegisterType<AlfaService>().As<IService>().WithMetadata("Key", "a");
builder.RegisterType<BravoService>().As<IService>().WithMetadata("Key", "b");
在 CompositeService 中,您将依赖于 IEnumerable<Meta<IService>>
public CompositeService(IEnumerable<Meta<IService>> services)
{
_services = services.ToDictionary(m => (String)m.Metadata["Key"], m => m.Value);
}
如果您不想在 CompositeService
上引入对 Meta
的依赖,您可以使用自定义 Parameter
将您的 IEnumerable<Meta<IService>>
转换为 IDictionary<String, IService>
public class ServiceParameter : Parameter
{
public override Boolean CanSupplyValue(ParameterInfo pi,
IComponentContext context, out Func<Object> valueProvider)
{
valueProvider = null;
if (pi.Name == "services"
&& pi.ParameterType == typeof(Dictionary<String, IService>))
{
valueProvider = () =>
{
IEnumerable<Meta<IService>> services =
context.Resolve<IEnumerable<Meta<IService>>>();
return services.ToDictionary(m => (String)m.Metadata["Key"],
m => m.Value);
};
}
return valueProvider != null;
}
}
下面的示例代码基本上是调用了多个dummy服务,然后合并结果。 (在实际应用中,它们将是网络服务。)
问题: 创建一个新的 ContainerBuilder 实例是个好习惯吗?请在 Main 方法中查看几个 *****。
如果没有,你能给我指明正确的方向吗?我愿意接受任何建议。
注意: Build() 或 Update() 方法只能在 ContainerBuilder 上调用一次。
输出
主要
private static void Main(string[] args)
{
var builder = new ContainerBuilder();
var container = builder.Build();
// ***** Create a new instance of ContainerBuilder *****
builder = new ContainerBuilder();
builder.RegisterType<AlfaService>().As<IService>().Named<IService>("a");
builder.RegisterType<BravoService>().As<IService>().Named<IService>("b");
builder.Update(container);
// ***** Create a new instance of ContainerBuilder *****
builder = new ContainerBuilder();
var services = new Dictionary<string, IService>
{
{"a", container.ResolveNamed<IService>("a")},
{"b", container.ResolveNamed<IService>("b")}
};
builder.RegisterType<CompositeService>().As<ICompositeService>()
.WithParameter("services", services);
builder.Update(container);
// The following is for testing purpose only.
// In real application, I'll inject ICompositeService to MVC controller.
using (ILifetimeScope scope = container.BeginLifetimeScope())
{
IList<int> ids = scope.Resolve<ICompositeService>().GetIdsBySource("a");
Console.WriteLine("AlfaService: " + string.Join(", ", ids));
ids = scope.Resolve<ICompositeService>().GetAllIds();
Console.WriteLine("All Services: " + string.Join(", ", ids));
}
Console.ReadLine();
}
接口
public interface ICompositeService
{
IList<int> GetIdsBySource(string source);
IList<int> GetAllIds();
}
public interface IService
{
IList<int> GetIds();
}
服务
public class CompositeService : ICompositeService
{
private readonly Dictionary<string, IService> _services;
public CompositeService(Dictionary<string, IService> services)
{
_services = services;
}
public IList<int> GetIdsBySource(string source)
{
return _services.Where(x => x.Key == source)
.Select(x => x.Value).First().GetIds();
}
public IList<int> GetAllIds()
{
return _services.SelectMany(x => x.Value.GetIds()).ToList();
}
}
public class AlfaService : IService
{
public IList<int> GetIds() { return new List<int> {1, 2, 3}; }
}
public class BravoService : IService
{
public IList<int> GetIds() { return new List<int> {4, 5, 6}; }
}
要解决参数中的问题,您不必构建容器。构建容器需要时间,应尽可能避免。
解决参数内部问题的最简单方法是使用 WithParameter
方法,如下所示:
builder.RegisterType<CompositeService>()
.As<ICompositeService>()
.WithParameter((pi, c) => pi.Name == "services", (pi, c) =>
{
return new Dictionary<string, IService> {
{ "a", c.ResolveNamed<IService>("a") },
{ "b", c.ResolveNamed<IService>("b") }
};
});
另一种解决方案是创建您自己的 Parameter
public class ServiceParameter : Parameter
{
public override Boolean CanSupplyValue(ParameterInfo pi,
IComponentContext context, out Func<Object> valueProvider)
{
valueProvider = null;
if (pi.Name == "services"
&& pi.ParameterType == typeof(Dictionary<String, IService>))
{
valueProvider = () =>
{
return new Dictionary<string, IService> {
{ "a", context.ResolveNamed<IService>("a") },
{ "b", context.ResolveNamed<IService>("b") }
};
};
}
return valueProvider != null;
}
}
并以这种方式注册:
builder.RegisterType<CompositeService>()
.As<ICompositeService>()
.WithParameter(new ServiceParameter());
在您的情况下,您可能想要使用 Metadata
而不是 命名服务builder.RegisterType<AlfaService>().As<IService>().WithMetadata("Key", "a");
builder.RegisterType<BravoService>().As<IService>().WithMetadata("Key", "b");
在 CompositeService 中,您将依赖于 IEnumerable<Meta<IService>>
public CompositeService(IEnumerable<Meta<IService>> services)
{
_services = services.ToDictionary(m => (String)m.Metadata["Key"], m => m.Value);
}
如果您不想在 CompositeService
上引入对 Meta
的依赖,您可以使用自定义 Parameter
将您的 IEnumerable<Meta<IService>>
转换为 IDictionary<String, IService>
public class ServiceParameter : Parameter
{
public override Boolean CanSupplyValue(ParameterInfo pi,
IComponentContext context, out Func<Object> valueProvider)
{
valueProvider = null;
if (pi.Name == "services"
&& pi.ParameterType == typeof(Dictionary<String, IService>))
{
valueProvider = () =>
{
IEnumerable<Meta<IService>> services =
context.Resolve<IEnumerable<Meta<IService>>>();
return services.ToDictionary(m => (String)m.Metadata["Key"],
m => m.Value);
};
}
return valueProvider != null;
}
}