在没有XML配置的情况下使用ImageResizer.net加载Autorotate插件的最佳方法

时间:2015-02-05 14:17:07

标签: c# dependency-injection imageresizer

我正在使用以下内容调整图片大小:

public interface IImageService
{
    byte[] ResizeImage(byte[] imageBytes, ImageFormat format, int thumbnailWidth = 150, bool autoRotate = false);
}

public ImageService : IImageService
{

    public byte[] ResizeImage(byte[] imageBytes, ImageFormat format, int thumbnailWidth = 150, bool autoRotate = false)
    {
        byte[] outputBytes = null;
        using (var outStream = new MemoryStream())
        {
            new ImageResizer.Plugins.Basic.AutoRotate().Install(Config.Current);
            var r = new ResizeSettings { Width = thumbnailWidth, Quality = 90, Mode = FitMode.Max };
            r.Add("autorotate", "true");
            ImageBuilder.Current.Build(imageBytes, outStream, r);
            outputBytes = outStream.ToArray();
        }

        return outputBytes;
    }

}

代码可以工作,但API让我的代码看起来很不愉快,即行:

new ImageResizer.Plugins.Basic.AutoRotate().Install(Config.Current);

ImageBuilder.Current.Build(imageBytes, outStream, r);

正如您所看到的,我已经将整个方法包装在类和接口中,因此我可以在没有这些依赖项的情况下对其他代码进行单元测试,但仍然看起来很讨厌。

有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

SOLID原则的角度来看,你正在做的事情看起来很好,因为:

  • 本课程只承担一项责任,使课程变得小巧且易于维护,从而坚持Single Responsibility Principle
  • 由于已定义的界面,您可以添加横切关注点,例如缓存,而无需更改此实现和使用者,从而遵守Open/Closed Principle
  • 您将接口定义为窄(一种方法),其API以对消费者有用的方式描述(而不是复制外部库的API),您实际上可以隐藏外部库应用程序的核心部分,因此遵守Interface Segregation Principle
  • 由于您定义的抽象没有指定有关给定实现的任何详细信息,因此您可以轻松测试应用程序并允许您交换实现而无需对客户端进行任何更改,甚至允许您部署单独实施 - 如果您愿意,这意味着您遵守Dependency Inversion Principle

因此,从设计和可维护性的角度来看,我会说你正在做的事情非常好。

您对此类中的代码有些担心。我这里没有看到问题。是的,我同意,ImageResizer暴露的API很难看,但是你无法做到这一点 - 也不应该这样做。您已经从应用程序中优雅地抽象出了这个丑陋的API。您的界面是端口,应用程序和ImageResizer之间的ImageServicethe adapter。所以它必须处理ImageResizer API。您可以尝试再次抽象,但这会很奇怪,只会导致代码更复杂,因为您希望此类是系统中唯一需要依赖ImageResizer的类。

尽管如此,我发现奇怪的是new AutoRotate().Install(Config.Current)电话;特别是每次通话都这样做!我对ImageResizer一无所知,所以可能需要这样做,但我的第一个直觉是将此代码移动到静态构造函数,以允许它只为app域调用一次。