C# 我可以全局设置要使用的接口实现吗?

C# 我可以全局设置要使用的接口实现吗?,c#,interface,global-variables,interface-implementation,multiple-interface-implem,C#,Interface,Global Variables,Interface Implementation,Multiple Interface Implem,我有一个界面: public interface IHHSDBUtils { void SetupDB(); bool TableExists(string tableName); . . . …具有多个实施者: public class SQLiteHHSDBUtils : IHHSDBUtils public class SQCEHHSDBUtils : IHHSDBUtils public class FlatfileHHSDBUtils : IHHSDBUti

我有一个界面:

public interface IHHSDBUtils
{
    void SetupDB();

    bool TableExists(string tableName);
    . . .
…具有多个实施者:

public class SQLiteHHSDBUtils : IHHSDBUtils
public class SQCEHHSDBUtils : IHHSDBUtils
public class FlatfileHHSDBUtils : IHHSDBUtils
public class TestHHSDBUtils : IHHSDBUtils
我希望能够从全局可访问的位置指定要使用的实现者,例如:

public static class HHSConsts
{
    public static IHHSDBUtils hhsdbutil = SQLiteHHSDBUtils;
…然后在应用程序中的任何位置这样称呼它:

private HHSDBUtils hhsdbutils { get; set; }
. . .
hhsdbutils = new HHSConsts.hhsdbutil;
hhsdbutils.SetupDB();

这可能吗?我得到,“'SqliteHHSButils'是一个'类型',但它像一个'变量'一样被用于上面对HHSButil的赋值。

您可以通过为每个类型创建一个枚举来实现poormans工厂,并使用一个静态工厂方法为您创建类型。我尽可能地接近您当前的代码片段

public enum HHSDBUtilsTypes 
{
    Sqllite,
    SQCE,
    Flatfile,
    Test
}

public static class HHSConsts
{
    private const string implementation = HHSDBUtilsTypes.Sqllite; // you might read this from the config file

    public static IHHSDBUtils GetUtils()
    {
         IHHSDBUtils impl;
         switch(implementation)
         {
            case HHSDBUtilsTypes.Sqllite:
               impl = new SQLiteHHSDBUtils();
            break;
            case HHSDBUtilsTypes.SQCE:
               impl = new SQCEHHSDBUtils();
            break;
            case HHSDBUtilsTypes.Sqllite:
               impl = new FlatfileHHSDBUtils();
            break;
            default:
               impl = new TestHHSDBUtils();
            break;
         }
         return impl;
    }
}
你可以这样使用它:

private IHHSDBUtils hhsdbutils { get; set; }
//. . .
hhsdbutils = HHSConsts.GetUtils();
hhsdbutils.SetupDB();
另一个选择是使用

确保测试和度量性能,特别是如果您需要经常通过这些方法中的任何一种实例化许多类型

如果您想要更多控制,请使用依赖项注入/反转控制框架,如:

请注意,所有这些框架都有其强大的功能,但同时也增加了复杂性。如果您觉得必须选择一个框架,那么将可维护性和可学习性作为主要要求


如果您使用依赖项注入(为什么不是?),您可以告诉di容器在组合根目录中使用哪个实现。按照当前编写的方式,您只需新建公共静态IHHSDBUtils HHSBUTIL=new SQLITEHSDBUTILS();您可以使用服务定位器,该定位器根据配置文件解析正确的实例(不过,这也被视为反模式)。或者,您可以查看IoC容器来配置要解析的实例。@reggaeguitar:DI在我看来似乎有点像怪物;它让我想起将梯形销钉强行插入球形孔中。这很难理解,因此很难维护,而且需要第三方“容器”“让它运作良好。对我来说,这表明这有点不自然,就像把Cyrano de Bergerac的鼻子贴在弗兰肯斯坦博士的怪物上一样。IOW:我正在努力避免DI。随着权力的到来,复杂性越来越大,我无法告诉你应该做什么和不应该做什么,但我可以说,DI在我的职业生涯中为我节省了数百个小时。在.NET中购买依赖注入(MarkSeemann的书)并阅读它,您将感谢我。想象一下,任何时候你需要一个类中的依赖项,你只要把它添加到ctor签名中就可以了!很高兴有你。旁注:在没有依赖注入的情况下编写单元测试几乎是不可能的,这会导致更干净的设计和体系结构。@reggaeguitar:好吧,也许你有一个观点(我有,这就是我为什么穿罩袍);但这是一个WindowsCE项目,我怀疑它是否能够在中使用DI。NET的精简版在看到自己的影子时使用地震,gescwhweige denn so einen Schlammassel。我使用过温莎城堡,发现它很尴尬,很难摸索;如果有人不得不维护它,甚至我自己在一段时间内没有查看代码,它会是什么样子:一场噩梦!好的,我自己并没有使用它,但让我补充一下,作为警告,您可以使用Castle Windsor在两行中配置整个应用程序,就像这样
var container=new WindsorContainer()_Register(Classes.FromThisAssembly().InNamespace(“YourNamespace”).WithService.DefaultInterfaces().LifestyleTransient())只要您将类命名为与接口相同的名称(减去前导的“I”),这将起作用。我真的不是吗hard@reggaeguitar当然,但是你的例子让我笑了。。。如果你在学习曲线的顶端甚至php变得容易。。。
 const string fulltypename = "Your.Namespace.SQLiteHHSDBUtils"; // or read from config;
 hhsdbutils = (HHSDBUtils) Activator.CreateInstance(null, fulltypename).Unwrap();