是原始的构造函数的参数使用IoC容器时,一个坏主意? [英] Are primitive constructor parameters a bad idea when using an IoC Container?

查看:124
本文介绍了是原始的构造函数的参数使用IoC容器时,一个坏主意?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

标准新手免责声明:我是新来的IoC和我得到的混合信号。我正在寻找在以下情况的一些指导,请。

Standard newbie disclaimer: I'm new to IoC and am getting mixed signals. I'm looking for some guidance on the following situation please.

假设我有以下的接口和实现:

Suppose I have the following interface and implementation:

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
    }
}

我越来越糊涂我是否应该只发送接口/依存的构造函数,创建一些参数对象并把它传递给构造或保持原样,并在解决一个实例时的参数传递。

I'm getting confused whether I should only send interface/dependencies to the constructor, create some parameter object and pass it to the constructor or keep it as is and pass in the parameters at the time of resolving an instance.

那么,有没有设置此code的工作最好的IoC容器的一种比较正确的做法?要么以下的是preferred设计方面超过我目前的布局?

So is there a more correct way of setting up this code to work best with an IoC container? Would either of the following be preferred design-wise over my current layout?

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,我需要执行两种方法,有必要采取每种方法相同​​的值。这就是为什么我通过构造函数传递的状态。

I don't like that I'm passing in the exact same thing in both cases (except the destination folder). In the current implementation of the IImageFileGenerator, I need to execute both methods and the same values were needed for each method. That is why I passed the state in via the constructor.

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
    }
}

这做法甚至可能被调整为马克塞曼的这里

This approach may even be tweaked to a Facade Service (previously called aggregate services) as mentioned by Mark Seemann here.

我也看到了,你可以使用属性这些值和使用属性注入,不过好像是不再pferred $ P $(autofac提到的构造函数注入preferred ... Ninject相信即便除去2版本的功能)。

I've also read that you could use properties for those values and use property injection, though it seems like that is not preferred anymore (autofac mentions constructor injection is preferred... Ninject I believe even removed the ability in version 2).

另外我读过,你也可以创建一个初始化方法,并确保性能在那里设置。

Alternatively I've read that you can also create an initialize method and ensure that the properties are set in there.

这么多的选择,当我阅读更多关于这个东西我越来越糊涂了。我敢肯定,没有确切的正确方法(也许有,至少在这个例子???),但也许有人可以提供每一种方法的优点和缺点。或者,也许有,我已经完全错过另一种方法。

So many options and I'm getting more confused as I read more about this stuff. I'm sure there is no definitive correct way (or maybe there is, at least for this example???), but maybe someone can provide pros and cons of each approach. Or maybe there is another approach that I've totally missed.

我现在认识到这个问题可能有点主观上侧(与真的不止一个问题),但我希望你能原谅我,并提供一定指引。

I realize now that this question is probably a little on the subjective side (and is really more than one question), but I'm hoping you can forgive me and provide some guidance.

PS - 我目前正试图用我的手autofac的情况下影响其设计可能更适合

PS - I'm currently trying my hand with autofac in case that influences which design may fit better.

注意:我已经作出了code左右的目标文件夹略有变化...它不使用RenameFiles(可能对你的答案轴承)

推荐答案

好吧,我结束了在读这本书依赖注入后,重新设计这一点。净(我强烈推荐这本书给任何面向对象的开发者,而不仅仅是.NET开发人员,而不仅仅是那些有兴趣使用IoC容器!)。

Well I ended up redesigning this after reading the book Dependency Injection in .Net (I highly recommend this book to any object-oriented developer, not just .Net developers and not just those interested in using an IoC container!).

我现在已经得到了在域装配如下:

I've now got the following in a Domain assembly:

public interface IImageFileService
{
    void RenameFiles();
    void CopyFiles(); 
}

public interface IImageLinkMapRepository
{
    IList<ImageLink> GetImageLinks(); 
}

这些接口然后在装配的FileAccess我创建实现:

Then in a FileAccess assembly I've created implementations for these interfaces:

public class ImageFileService : IImageFileService
{
    public ImageFileService(IImageLinkMapRepository repository)
    {
        // null checks etc. left out for brevity
        _repository = repository;
    }

    public void RenameFiles()
    {
        // rename files, using _repository.GetImageLinks(), which encapsulates
        // enough information for it to do the rename operations without this
        // class needing to know the specific details of the source/dest dirs.
    }

    public void CopyFiles() 
    { 
        // same deal as above
    }
}

所以基本上,我已经删除了原始类型,需要在我的构造,至少在这个类。在某些时候,我确实需要这些信息,但注入ImageLinkMa prepository那里的信息更有意义。我用 autofac命名参数来处理它们注射

所以我想回答我的问题,的原始的构造函数的参数是一个好主意,如果他们是有意义的,但要确保你把它们属于他们的地方。如果事情似乎并没有被正确jiving,大概可以通过重新思考设计的改进

So I guess to answer my own question, primitive constructor parameters are a good idea if they make sense, but make sure you put them where they belong. If things don't seem to be jiving properly, it can probably be improved by rethinking the design.

这篇关于是原始的构造函数的参数使用IoC容器时,一个坏主意?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆