我有一个使用 AutoFac 从二进制文件夹中的程序集构建容器的类。这实质上是遍历 dll 并使用接口注册类:
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();
}
这工作正常,我可以创建我需要的类的实例。我遇到的问题是,其中有几个类是单例的(例如 Redis 缓存),因此需要注册为单例。在代码中,它们是使用 Lazy<> 定义的:
private static readonly Lazy<CacheManager> _instance = new Lazy<CacheManager>(() => new CacheManager());
public static ICacheManager Instance
{
get { return _instance.Value; }
}
我想知道的是是否有某种方法可以告诉AutoFac某些类需要注册为单例。我猜我可以在构建容器后对其进行检查并将特定定义更改为单例,但是如果我可以让 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();
}
这并不理想,但它有效。