在C#中创建注入构造函数的接口的最佳方法是什么?

在C#中创建注入构造函数的接口的最佳方法是什么?,c#,interface,dependency-injection,strategy-pattern,C#,Interface,Dependency Injection,Strategy Pattern,我在一个项目中工作,外部数据从不同的来源获取,比如数据库、3个外部web API、web配置。 为了避免紧密耦合,在我的类构造函数中使用并传递了一些接口,例如: public Dog(IDataAccess dataAccess, IConverter converter, IConfigAccess configAccess, ITimezoneAccess timezoneAccess) public Cat(IDataAccess dataAccess, IConverter c

我在一个项目中工作,外部数据从不同的来源获取,比如数据库、3个外部web API、web配置。 为了避免紧密耦合,在我的类构造函数中使用并传递了一些接口,例如:

public Dog(IDataAccess dataAccess, IConverter converter, IConfigAccess configAccess,
    ITimezoneAccess timezoneAccess)

public Cat(IDataAccess dataAccess, IConverter converter, IConfigAccess configAccess, 
    ITimezoneAccess timezoneAccess)

public Duck(IDataAccess dataAccess, IConverter converter, IConfigAccess configAccess, 
    ITimezoneAccess timezoneAccess)
它帮助我们进行单元测试,因为我们创建了这些接口的模拟实现

在开发代码时,所有类之间都有一些通用函数,如Datetime操作、固定值方法等。我决定创建一些静态类,将此功能划分为特定类,如DatetimeHelper、FixedCalculationHelper、StringHandlingHelper等

我得到的建议是避免使用这些静态类,将它们转换为带有接口的策略,并将它们作为其他外部数据访问接口传递到构造函数中

  • 当我应用它时,我的类的构造函数将有很多接口参数,例如:

    public Dog(IDataAccess dataAccess, IConverter converter, IConfigAccess configAccess,
        ITimezoneAccess timezoneAccess)
    
    public Cat(IDataAccess dataAccess, IConverter converter, IConfigAccess configAccess, 
        ITimezoneAccess timezoneAccess)
    
    public Duck(IDataAccess dataAccess, IConverter converter, IConfigAccess configAccess, 
        ITimezoneAccess timezoneAccess)
    
    公用狗(IDataAccess数据访问、IConverter转换器、IConfigaAccess配置访问、, ITimezoneAccess timezoneAccess、IStringHandling stringHandler、, IDatetimeHelper datetimeHelper…等

  • 处理这种情况最优雅/最好的方式是什么? (不确定此处是否使用了一些技术,如容器或类似物)

  • 为什么将这个静态类转换成接口/实现策略更好(即使这个方法是静态的,比如CalculateArea(int value1,int value2))

  • 欢迎任何评论或解释。请提前感谢。

    使用接口的目的是为抽象编码,而不是为消除依赖关系的具体编码


  • 将许多接口传递给构造函数是可以的,但是您不想传递具体的类。如果您只是不希望构造函数有参数,可以使用setter注入而不是构造函数注入

    public class Duck
    {
        IDataAccess DataAccess { get; set; }
        IConverter Converter { get; set; }
        IConfigAccess ConfigAccess { get; set; }
        ITimezoneAccess TimezoneAccess { get; set; }
    
        public Duck()
        {
             // parameterless contructor 
        }
    }
    
  • 通过使用接口,更改实现将更容易。它使您能够更好地控制程序的结构。您希望您的类可以进行扩展,但不能进行修改,这是最重要的。在我看来,我将使helpers扩展方法,并放弃为它们创建接口


  • 使用接口的目的是按照抽象而不是具体化进行编码,从而消除依赖关系


  • 将许多接口传递给构造函数是可以的,但是您不想传递具体的类。如果您只是不希望构造函数有参数,可以使用setter注入而不是构造函数注入

    public class Duck
    {
        IDataAccess DataAccess { get; set; }
        IConverter Converter { get; set; }
        IConfigAccess ConfigAccess { get; set; }
        ITimezoneAccess TimezoneAccess { get; set; }
    
        public Duck()
        {
             // parameterless contructor 
        }
    }
    
  • 通过使用接口,更改实现将更容易。它使您能够更好地控制程序的结构。您希望您的类可以进行扩展,但不能进行修改,这是最重要的。在我看来,我将使helpers扩展方法,并放弃为它们创建接口


  • 使用接口的目的是按照抽象而不是具体化进行编码,从而消除依赖关系


  • 将许多接口传递给构造函数是可以的,但是您不想传递具体的类。如果您只是不希望构造函数有参数,可以使用setter注入而不是构造函数注入

    public class Duck
    {
        IDataAccess DataAccess { get; set; }
        IConverter Converter { get; set; }
        IConfigAccess ConfigAccess { get; set; }
        ITimezoneAccess TimezoneAccess { get; set; }
    
        public Duck()
        {
             // parameterless contructor 
        }
    }
    
  • 通过使用接口,更改实现将更容易。它使您能够更好地控制程序的结构。您希望您的类可以进行扩展,但不能进行修改,这是最重要的。在我看来,我将使helpers扩展方法,并放弃为它们创建接口


  • 使用接口的目的是按照抽象而不是具体化进行编码,从而消除依赖关系


  • 将许多接口传递给构造函数是可以的,但是您不想传递具体的类。如果您只是不希望构造函数有参数,可以使用setter注入而不是构造函数注入

    public class Duck
    {
        IDataAccess DataAccess { get; set; }
        IConverter Converter { get; set; }
        IConfigAccess ConfigAccess { get; set; }
        ITimezoneAccess TimezoneAccess { get; set; }
    
        public Duck()
        {
             // parameterless contructor 
        }
    }
    
  • 通过使用接口,更改实现将更容易。它使您能够更好地控制程序的结构。您希望您的类可以进行扩展,但不能进行修改,这是最重要的。在我看来,我将使helpers扩展方法,并放弃为它们创建接口


  • 如果您不需要任何DI容器,对于助手,我建议您使用我所称的“抽象接口” 创建空接口:

    public interface IDateTimerHelper { }
    public interface IFixedCalculationsHelper { }
    
    然后在扩展类中实现

    public static class DateTimerHelperExtension { public static void HelpMeForDateTimering(this IDateTimerHelper dth/*, params*/) { //Help here; } public static void HelpMe(this IDateTimerHelper dth/*, params*/) { //Help here; } } public static class FixedCalculationsHelperExtension { public static void HelpMeForFixedCalculations(this IFixedCalculationsHelper fch/*, params*/) { //implement here } public static void HelpMe(this IFixedCalculationsHelper fch/*, params*/) { //implement here } } 公共静态类DateTimerHelperExtension { public static void HelpMeForDateTimering(此IDateTimerHelper dth/*,参数*/) { //帮助这里; } 公共静态void HelpMe(此IDateTimerHelper dth/*,参数*/) { //帮助这里; } } 公共静态类FixedCalculationHelperExtension { 用于固定计算的公共静态void helpmeforFixedCalculationsHelper(此IFixedCalculationsHelper fch/*,params*/) { //在这里实施 } 公共静态void HelpMe(此IFExedCalculationHelper fch/*,params*/) { //在这里实施 } } 最后用这个

    public class Dog:IFixedCalculationsHelper,IDateTimerHelper { public Dog(/*other injections*/) { //Initialize } public void DoWork() { (this as IDateTimerHelper).HelpMe(); (this as IFixedCalculationsHelper).HelpMe(); this.HelpMeForDateTimering(); this.HelpMeForFixedCalculations(); } } 公共类狗:IFExedCalculationHelper、IDateTimerHelper { 公犬(/*其他注射*/) { //初始化 } 公共工作 { (这是IDateTimerHelper); (此为IFExedCalculationHelper)。HelpMe(); this.helpmeforatetimering(); this.HelpMeForFixedCalculations(); } }
    如果您不需要任何DI容器,对于助手,我建议您使用我所称的“抽象接口” 创建空接口:

    public interface IDateTimerHelper { }
    public interface IFixedCalculationsHelper { }
    
    然后在扩展类中实现

    public static class DateTimerHelperExtension { public static void HelpMeForDateTimering(this IDateTimerHelper dth/*, params*/) { //Help here; } public static void HelpMe(this IDateTimerHelper dth/*, params*/) { //Help here; } } public static class FixedCalculationsHelperExtension { public static void HelpMeForFixedCalculations(this IFixedCalculationsHelper fch/*, params*/) { //implement here } public static void HelpMe(this IFixedCalculationsHelper fch/*, params*/) { //implement here } } 公共静态类