Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “创建对象”;目录;不可知论图书馆_C#_Dependency Injection_Webforms_Ioc Container_Legacy Code - Fatal编程技术网

C# “创建对象”;目录;不可知论图书馆

C# “创建对象”;目录;不可知论图书馆,c#,dependency-injection,webforms,ioc-container,legacy-code,C#,Dependency Injection,Webforms,Ioc Container,Legacy Code,我正在开发一个内部库,供我所在公司的其他开发人员使用。我正在应用实体模式并遵循中所述的最佳实践 我的最终用户将是不同应用程序的开发人员。其中一些是没有DI的复杂遗留应用程序,另一些是具有DI和TDD的较新应用程序 现在,我正试图找出如何从一个没有实现DI的旧ASP.NET Webforms应用程序调用这个DI友好库,显然,我不能修改250+aspx页面来支持构造函数注入,因为它超出了我的项目范围。( ) 我的一个想法是为公共服务定位器创建一个静态全局包装器,以自动解决整个应用程序中的依赖关系:

我正在开发一个内部库,供我所在公司的其他开发人员使用。我正在应用实体模式并遵循中所述的最佳实践

我的最终用户将是不同应用程序的开发人员。其中一些是没有DI的复杂遗留应用程序,另一些是具有DI和TDD的较新应用程序

现在,我正试图找出如何从一个没有实现DI的旧ASP.NET Webforms应用程序调用这个DI友好库,显然,我不能修改250+aspx页面来支持构造函数注入,因为它超出了我的项目范围。( )

我的一个想法是为公共服务定位器创建一个静态全局包装器,以自动解决整个应用程序中的依赖关系:

public static class GlobalResolver
{
    public static T Resolve<T>()
    {
        return ServiceLocator.Current.GetInstance<T>();
    }
}
公共静态类GlobalResolver
{
公共静态T解析()
{
返回ServiceLocator.Current.GetInstance();
}
}
这种方法的好处是,我可以使用我的合成根目录中的任何IoC库(我目前使用的是Unity)。我会像这样使用GlobalResolver:

protected void OnClick(object sender, EventArgs e)
{
    IMailMessage message = MessageFactory.Create("Jack.Daniels@jjj.com", "John.Doe@jjj.com", "subject", "Body", true, MailPriority.High);
    GlobalResolver.Resolve<IMailer>().SendMail(message);
}
public static class CommonCatalog
{
    public static IMailer Mailer => ServiceLocator.Current.GetInstance<IMailer>();
    public static IMailMessageFactory MessageFactory => ServiceLocator.Current.GetInstance<IMailMessageFactory>();
    public static IFtpSecureClientFactory FTPClientFactory => ServiceLocator.Current.GetInstance<IFtpSecureClientFactory>();

    // And so on...
}
public static class Mailer
{
    public static IMailer Default
    {
        get { return new MailerBuilder().Create(); }
    }
}
protectedvoid OnClick(对象发送方,事件参数e)
{
IMailMessage=MessageFactory.Create(“杰克。Daniels@jjj.com约翰。Doe@jjj.com“,”主题“,”正文“,”真“,”优先权。高);
GlobalResolver.Resolve().SendMail(消息);
}
我喜欢这种方法,而且我认为它很干净,但是我公司的新手开发人员可能会对这条
GlobalResolver.Resolve
行感到困惑,所以我正在尝试看看是否有其他替代方法

我想到的一件事是这样的:

protected void OnClick(object sender, EventArgs e)
{
    IMailMessage message = MessageFactory.Create("Jack.Daniels@jjj.com", "John.Doe@jjj.com", "subject", "Body", true, MailPriority.High);
    GlobalResolver.Resolve<IMailer>().SendMail(message);
}
public static class CommonCatalog
{
    public static IMailer Mailer => ServiceLocator.Current.GetInstance<IMailer>();
    public static IMailMessageFactory MessageFactory => ServiceLocator.Current.GetInstance<IMailMessageFactory>();
    public static IFtpSecureClientFactory FTPClientFactory => ServiceLocator.Current.GetInstance<IFtpSecureClientFactory>();

    // And so on...
}
public static class Mailer
{
    public static IMailer Default
    {
        get { return new MailerBuilder().Create(); }
    }
}
公共静态类CommonCatalog
{
公共静态iMail=>ServiceLocator.Current.GetInstance();
公共静态IMailMessageFactory MessageFactory=>ServiceLocator.Current.GetInstance();
公共静态IFtpSecureClientFactory FTPClientFactory=>ServiceLocator.Current.GetInstance();
//等等。。。
}
简单地使用它:
CommonCatalog.Mailer.SendMail(message)。我公司的开发人员习惯于看到静态方法,我认为这种方法对他们来说可能是可取的

我的问题是:

  • 这是解决我问题的最好办法吗
  • 我是否违反了任何最佳实践
  • 是否有描述CommonCatalog类的设计模式?它是“门面”还是“代理”
  • TLDR:我公司的开发人员喜欢使用静态方法,但静态方法与DI和实体实践不兼容。有没有办法欺骗人们,让他们认为他们使用的是静态方法,但在幕后调用DI代码?

    如果你想避免这种情况(你应该这样做,因为这是一种反模式),那么使用
    GlobalResolver
    的第一个选项是不可能的,因为

    服务目录更接近于我在上的扩展文章中推荐的目录,尽管我通常不喜欢对象的聚合目录。当我不知道如何命名对象时,它总是让我感到不舒服,而像
    CommonCatalog
    这样的名称似乎太没有意义了

    相反,我更喜欢使用本文中描述的Fluent Builder模式制作基于实例的外观,因为当您发现需要向外观添加各种选项和开关时,它会更灵活

    但是,如果必须这样做,可以为每个立面添加静态方法。大概是这样的:

    protected void OnClick(object sender, EventArgs e)
    {
        IMailMessage message = MessageFactory.Create("Jack.Daniels@jjj.com", "John.Doe@jjj.com", "subject", "Body", true, MailPriority.High);
        GlobalResolver.Resolve<IMailer>().SendMail(message);
    }
    
    public static class CommonCatalog
    {
        public static IMailer Mailer => ServiceLocator.Current.GetInstance<IMailer>();
        public static IMailMessageFactory MessageFactory => ServiceLocator.Current.GetInstance<IMailMessageFactory>();
        public static IFtpSecureClientFactory FTPClientFactory => ServiceLocator.Current.GetInstance<IFtpSecureClientFactory>();
    
        // And so on...
    }
    
    public static class Mailer
    {
        public static IMailer Default
        {
            get { return new MailerBuilder().Create(); }
        }
    }
    
    如果可以想象该实例具有单例生存期,则可以使用,如下一个示例所示

    您可以用同样的方法实现默认MessageFactory,但这里使用的是Singleton设计模式:

    public static class MailMessageFactory
    {
        public static IMailMessageFactory Default { get } =
            new MailMessageFactoryBuilder().Create();
    }
    
    请注意,这也没有为实现使用服务定位器


    不过,需要明确的是,这些外观背后的内容可以根据可靠的原则轻松实现,但调用代码仍然很难做到这一点。

    我认为您已经回答了第二个问题;这种静态方法调用的方法违反了自年以来的最佳实践。描述第5章(反模式)和第6章(代码气味)中描述的大部分内容。但是,作为架构师,您需要考虑到当前对开发人员和遗留软件的理解,因此除了您之外,没有人能够回答第一个问题;这个问题的主观性很强,甚至可能会让你的问题结束。您的
    CommonCatalog
    使用Facade(+)、服务定位器(-)和环境上下文(-)。感谢您的输入。我在读你的书。我喜欢。干杯