【发布时间】:2011-12-31 11:07:39
【问题描述】:
标准新手免责声明:我是 IoC 新手,收到的信号不一。我正在寻找有关以下情况的一些指导。
假设我有以下接口和实现:
public interface IImageFileGenerator
{
void RenameFiles();
void CopyFiles();
}
public class ImageFileGenerator : IImageFileGenerator
{
private readonly IList<IImageLink> _links;
private readonly string _sourceFolder;
private readonly string _destinationFolder;
private readonly int _folderPrefixLength;
public ImageFileGenerator(IList<IImageLink> links, string sourceFolder, string destinationFolder)
{
_links = links;
_sourceFolder = sourceFolder;
_destinationFolder = destinationFolder;
_folderPrefixLength = 4;
}
public void RenameFiles()
{
// Do stuff, uses all the class fields except destination folder
}
public void CopyFiles()
{
// Do stuff, also uses the class fields
}
}
我很困惑是否应该只将接口/依赖项发送给构造函数,创建一些参数对象并将其传递给构造函数,还是保持原样并在解析实例时传递参数。
那么有没有更正确的方法来设置此代码以最好地与 IoC 容器配合使用?与我当前的布局相比,以下哪一项在设计上更受欢迎?
1.
public interface IImageFileGenerator
{
void RenameFiles(IList<IImageLink> links, string sourceFolder);
void CopyFiles(IList<IImageLink> links, string sourceFolder, stringDestFolder);
}
public class ImageFileGenerator : IImageFileGenerator
{
private readonly int _folderPrefixLength;
public ImageFileGenerator()
{
_folderPrefixLength = 4;
}
public void RenameFiles(IList<IImageLink> links, string sourceFolder)
{
// Do stuff
}
public void CopyFiles(IList<IImageLink> links, string sourceFolder, stringDestFolder)
{
// Do stuff
}
}
我不喜欢在两种情况下都传递完全相同的东西(目标文件夹除外)。在 IImageFileGenerator 的当前实现中,我需要执行这两个方法,并且每个方法都需要相同的值。这就是我通过构造函数传入状态的原因。
2.
public interface IImageFileGenerator
{
void RenameFiles();
void CopyFiles();
}
public class ImageLinkContext
{
// various properties to hold the values needed in the
// ImageFileGenerator implementation.
}
public class ImageFileGenerator : IImageFileGenerator
{
private readonly IList<IImageLink> _links;
private readonly string _sourceFolder;
private readonly string _destinationFolder;
private readonly int _folderPrefixLength;
public ImageFileGenerator(ImageLinkContext imageLinkContext)
{
// could also use these values directly in the methods
// by adding a single ImageLinkContext field and skip
// creating the other fields
_links = imageLinkContext.ImageLinks;
_sourceFolder = imageLinkContext.Source;
_destinationFolder = imageLinkContext.Destination;
_folderPrefixLength = 4;
}
public void RenameFiles()
{
// Do stuff, uses all the class fields except destination folder
}
public void CopyFiles()
{
// Do stuff, uses all the class fields
}
}
这种方法甚至可以调整为 Mark Seemann here 提到的外观服务(以前称为聚合服务)。
我还读到您可以为这些值使用属性并使用属性注入,尽管这似乎不再是首选(autofac 提到构造函数注入是首选... Ninject 我相信甚至删除了版本 2 中的功能)。
另外,我读到您还可以创建一个初始化方法并确保在其中设置属性。
有这么多的选择,当我阅读更多关于这些东西的信息时,我变得越来越困惑。我敢肯定没有明确的正确方法(或者至少对于这个例子来说可能有?),但也许有人可以提供每种方法的优缺点。或者也许还有另一种我完全错过的方法。
我现在意识到这个问题可能有点主观(实际上不仅仅是一个问题),但我希望你能原谅我并提供一些指导。
PS - 我目前正在尝试使用 autofac,以防影响哪种设计可能更适合。
注意:我对目标文件夹的代码做了一些细微的更改...... RenameFiles 不使用它(可能对您的回答有影响)。
【问题讨论】:
-
这里是关于注入 services 与 data 的相关讨论:stackoverflow.com/questions/1818539/…
-
@Peter Lillevold:有趣,我会花一些时间看看工厂代表。我可以看到它们派上用场。感谢您的链接(以及您回答中的附加文章:peterspattern.com/generate-generic-factories-with-autofac)。
标签: c# dependency-injection inversion-of-control ioc-container