如何在 Autofac 程序集扫描和注册期间有选择地更改生命周期范围?
How do I selectively change lifetime scope during Autofac assembly scanning and registration?
我有一个 class,它使用 AutoFac 从二进制文件夹中的程序集构建容器。这实质上是遍历 dll 并使用接口注册 classes:
private static void RegisterAssembly(ContainerBuilder builder, string assemblyNamePattern)
{
// Get the path to the currently executing assembly. We will load dll's from here only.
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (String.IsNullOrWhiteSpace(path))
return;
// Get a list of all the assemblies in this folder
var assembliesToRegister = (Directory.EnumerateFiles(path, assemblyNamePattern, SearchOption.TopDirectoryOnly)
.Select(Assembly.LoadFrom)
.ToArray());
// Register the dll's
builder.RegisterAssemblyTypes(assembliesToRegister).AsImplementedInterfaces();
}
工作正常,我可以创建我需要的 classes 的实例。我遇到的问题是这些 class 中有几个是单例(例如 Redis 缓存),因此需要这样注册。在代码中,它们是使用 Lazy<>:
定义的
private static readonly Lazy<CacheManager> _instance = new Lazy<CacheManager>(() => new CacheManager());
public static ICacheManager Instance
{
get { return _instance.Value; }
}
我想知道是否有某种方法可以告诉 AutoFac 某些 classes 需要注册为单例。我猜我可以在构建容器后检查容器并将特定定义更改为单例,但如果我能让 Autofac 在注册时自动执行它会更可靠。
作为一种廉价的解决方案,当扫描 DLL 时,您可以排除一个或多个接口:
// Register the dll's, except the singleton ones.
builder.RegisterAssemblyTypes(assembliesToRegister)
.AsImplementedInterfaces()
.Except<IOne>()
.Except<ITwo>();
这允许自动注册除单例之外的所有内容。接下来注册单例:
AddSingletonInstance<IOne>(builder, assembliesToRegister, "OneType");
AddSingletonInstance<ITwo>(builder, assembliesToRegister, "TwoType");
这依赖于扫描之前创建的汇编列表的通用方法:
private static void AddSingletonInstance<T>(ContainerBuilder builder, Assembly[] assembliesToRegister, string typeName)
{
var singletonType = (from asm in assembliesToRegister
from tt in asm.DefinedTypes
where tt.Name == typeName
select tt).FirstOrDefault();
if (singletonType != null)
builder.RegisterType(singletonType).As<T>().SingleInstance().ExternallyOwned();
}
虽然不理想,但很管用。
我有一个 class,它使用 AutoFac 从二进制文件夹中的程序集构建容器。这实质上是遍历 dll 并使用接口注册 classes:
private static void RegisterAssembly(ContainerBuilder builder, string assemblyNamePattern)
{
// Get the path to the currently executing assembly. We will load dll's from here only.
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (String.IsNullOrWhiteSpace(path))
return;
// Get a list of all the assemblies in this folder
var assembliesToRegister = (Directory.EnumerateFiles(path, assemblyNamePattern, SearchOption.TopDirectoryOnly)
.Select(Assembly.LoadFrom)
.ToArray());
// Register the dll's
builder.RegisterAssemblyTypes(assembliesToRegister).AsImplementedInterfaces();
}
工作正常,我可以创建我需要的 classes 的实例。我遇到的问题是这些 class 中有几个是单例(例如 Redis 缓存),因此需要这样注册。在代码中,它们是使用 Lazy<>:
定义的 private static readonly Lazy<CacheManager> _instance = new Lazy<CacheManager>(() => new CacheManager());
public static ICacheManager Instance
{
get { return _instance.Value; }
}
我想知道是否有某种方法可以告诉 AutoFac 某些 classes 需要注册为单例。我猜我可以在构建容器后检查容器并将特定定义更改为单例,但如果我能让 Autofac 在注册时自动执行它会更可靠。
作为一种廉价的解决方案,当扫描 DLL 时,您可以排除一个或多个接口:
// Register the dll's, except the singleton ones.
builder.RegisterAssemblyTypes(assembliesToRegister)
.AsImplementedInterfaces()
.Except<IOne>()
.Except<ITwo>();
这允许自动注册除单例之外的所有内容。接下来注册单例:
AddSingletonInstance<IOne>(builder, assembliesToRegister, "OneType");
AddSingletonInstance<ITwo>(builder, assembliesToRegister, "TwoType");
这依赖于扫描之前创建的汇编列表的通用方法:
private static void AddSingletonInstance<T>(ContainerBuilder builder, Assembly[] assembliesToRegister, string typeName)
{
var singletonType = (from asm in assembliesToRegister
from tt in asm.DefinedTypes
where tt.Name == typeName
select tt).FirstOrDefault();
if (singletonType != null)
builder.RegisterType(singletonType).As<T>().SingleInstance().ExternallyOwned();
}
虽然不理想,但很管用。