使用Autofac时将主应用程序与其他依赖项隔离
我正在使用Autofac,我想将主应用程序与我在Autofac容器中注册的所有依赖项隔离。使用Autofac时将主应用程序与其他依赖项隔离
这是一个可能的方案:
我有一个包含4个项目中的溶液。 ProjectA是主应用程序,它是一个C#控制台程序,包含我重命名为ClassA的常用静态类程序。 ProjectB只包含ClassB,而projectC包含ClassC。 ClassB和ClassC都位于它们的接口IClassB和IClassC后面,这些接口放置在projectD中。 ClassA通过IClassB调用ClassB的方法。 ClassB通过IClassC调用ClassC的方法。
的ClassA里面我建立Autofac容器并注册项目B和C的组件:
static class ClassA
{
static void Main()
{
var builder = new ContainerBuilder();
builder.RegisterType<ClassB>().As<IClassB>();
builder.RegisterType<ClassC>().As<IClassC>();
IContainer container = builder.Build();
}
}
此时项目A具有的所有其他项目的引用,即使使用的app.config或者基于寄存器的依赖关系Autofac配置。
有没有什么办法可以让ProjectA只依赖放置接口的ProjectD,而不是依赖于所有项目?
这是你可以分两个步骤做:
第一步将是具有在同一个地方的所有项目的依赖关系。 要为项目B,C,D执行此操作,请单击属性>构建>输出路径设置项目A的bin/debug目录。 现在,当您编译解决方案时,您应该在项目中看到A,B,C,D的dll A的bin/debug文件夹。
接下来,你需要把所有从组件您指定选择的依赖注入容器的注册它们的类型,在这种情况下Autofac,像这样:
class ClassA
{
static void Main(string[] args)
{
// specify here the projects needed to resolve your types
var projects = new List<string> { "ProjectB", "ProjectC", "ProjectD" };
var types = GetAllTypes(projects);
var interfaces = types.Where(t => t.IsInterface).ToList();
// init autofac container builder
var builder = new ContainerBuilder();
// add types to the builder
foreach (var interfaceType in interfaces)
{
var implementingType = types.FirstOrDefault(t => interfaceType.IsAssignableFrom(t) && !t.IsInterface);
if (implementingType != null)
{
builder.RegisterType(implementingType).As(interfaceType);
}
}
var container = builder.Build();
// test ClassB and ClassC can be instantiated through their interface
using (var scope = container.BeginLifetimeScope())
{
var classB = scope.Resolve<IClassB>();
var classC = scope.Resolve<IClassC>();
}
}
// get all the classes and interfaces from the selected projects
private static List<Type> GetAllTypes(List<string> projects) =>
Directory.EnumerateFiles(AppDomain.CurrentDomain.BaseDirectory)
.Where(f => f.ToLower().EndsWith(".dll"))
.Where(f => projects.Any(a => Assembly.ReflectionOnlyLoadFrom(f).GetName().Name.StartsWith(a)))
.Select(a => Assembly.ReflectionOnlyLoadFrom(a).FullName)
.Select(Assembly.Load)
.SelectMany(a => a.GetTypes())
.ToList();
}
注意 - 这方法假定您想要为每个接口注册一种类型。做其他事情需要更复杂的注册策略,但您可以随时添加。
似乎是一种确实的方式。在我将您的答复标记为接受之前,我会再等一会儿,看看是否提出了其他替代方案。 –
组合根必须知道所有类型。你不能没有 –