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();