我的想法已经用完了,所以我决定在这里问一些。目前我正在研究一个 .Net 类库,我决定将库类也拆分为一个服务类(它使用 IO、config(。
在库内部,我正在使用Autofac IoC进行DI。但无论如何,事实证明,在将库添加到我的项目中后,该项目有自己的 Autofac IoC,我从我的 ViewModelLocator 中得到了异常:
无法解析参数"G_Hoover.服务.日志记录.IFileService 构造函数 'Void .ctor (...( 的文件服务'
注意:IFileService
是库的依赖项,而不是应用程序项目。在库内,我正在注册:
public static IContainer BootStrap()
{
var builder = new ContainerBuilder();
builder.RegisterType<FileService>()
.As<IFileService>().SingleInstance();
//other services
return builder.Build();
}
这意味着,项目的 IoC 想要解析我的类库中的依赖项。
经过一些研究,我发现了这个 andswer,建议在我的库中内部解决依赖项,而项目不知道它们。但是怎么做呢?
目前我的方法是,根据这篇关于异步 init 的文章,从我调用库的公开初始属性的应用程序项目中,并且使用此属性,我RunConfigAsync()
在我的库中尝试解决我的库依赖项:
private async Task RunConfigAsync()
{
IContainer container = BootStrapper.BootStrap();
container.Resolve<IConfigService>();
container.Resolve<IFileService>();
container.Resolve<IStringService>();
ConfigModel config = _configService.GetConfig();
//do some other config and init stuff
}
但问题是,正如我所相信的那样,我在应用程序项目中的 ViewModelLocator 正在调用我的 ViewModel,它将我的库作为依赖项,然后再解析我的库中的依赖项。所以我尝试在 VMLocator 中解析我的库,如下所示:
public class ViewModelLocator
{
IContainer _container;
public ViewModelLocator()
{
_container = BootStrapper.BootStrap();
_container.Resolve<IParamsLogger>();
}
public BrowserViewModel BrowserViewModel
{
get
{
return _container.Resolve<BrowserViewModel>();
}
}
// other viewmodels below
}
不幸的是,我仍然像以前一样遇到同样的异常。现在,在使用Autofac(或其他IoC框架(时,我不知道如何在库内部解决依赖关系,我们到了需要向更有经验的开发人员寻求建议的地步。
更新
受到这篇文章和这个 SO 答案的启发,我提出了一种解决方案。如果我错了,请纠正我。
这里的全部内容都是关于隐藏库依赖项,以免看到应用程序项目。否则,应用程序项目会哭泣,但库依赖项未在他的 IoC 中注册。但是它们已经在库 IoC 中注册,我们不想再这样做了。右?目前的问题是,它们被注入到库公共构造函数中,并且也被应用程序项目看到。
正如有人建议的那样,立面图案来这里是为了救援。我们应该将依赖项隐藏在内部,并在初始化时Resolve
库类中的某个位置的外观。我在下面编造的简单示例,显示了我如何在库 IoC 中将库服务注册为单例:
public class Booter
{
public static IContainer BootStrap()
{
var builder = new ContainerBuilder();
builder.RegisterType<FilesService>()
.As<IFilesService>().SingleInstance();
builder.RegisterType<ControlsService>()
.As<IControlsService>().SingleInstance();
builder.RegisterType<Facade>()
.AsSelf().SingleInstance();
return builder.Build();
}
}
在外观中,我们正在注入库依赖项:
public class Facade
{
IFilesService _fileService;
IControlsService _controlsService;
public Facade(IFilesService filesService, IControlsService controlsService)
{
_fileService = filesService;
_controlsService = controlsService;
FilesService = _fileService;
ControlsService = _controlsService;
}
public IFilesService FilesService { get; }
public IControlsService ControlsService { get; }
}
接下来,在我们的库中,首先需要调用Initialize
,并在 façade 内部Resolve
调用 ,并且对于接口,我们声明 façade 属性,它们实际上是注入的服务:
public class MainService : IMainService
{
IFilesService _fileService;
IControlsService _controlsService;
IContainer _container;
public MainService()
{
Initialize();
}
public void Initialize()
{
_container = Booter.BootStrap();
var aggregator = _container.Resolve<Facade>();
_fileService = aggregator.FilesService;
_controlsService = aggregator.ControlsService;
}
public UiControlsModel SwitchOff()
{
return _controlsService.SwitchOff();
}
public UiControlsModel SwitchOn()
{
return _controlsService.SwitchOn();
}
}
我真的希望它不是任何反模式。