Могу ли я глобально настроить реализацию интерфейса для использования?
У меня есть интерфейс:
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();
Это возможно? Я понимаю, что "SQLiteHHSDBUtils" является "типом", но используется как "переменная" с присваиванием hhsdbutil выше.
1 ответ
Вы могли бы реализовать реализацию Factory для badmans, создав enum для каждого типа и имея статический метод factory, который создает тип для вас. Я остаюсь как можно ближе к вашим текущим фрагментам кода.
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();
Другой вариант - использовать Activator.CreateInstance.
const string fulltypename = "Your.Namespace.SQLiteHHSDBUtils"; // or read from config;
hhsdbutils = (HHSDBUtils) Activator.CreateInstance(null, fulltypename).Unwrap();
Обязательно проверяйте и измеряйте производительность, особенно если вам нужно часто создавать экземпляры многих типов с помощью любого из этих методов.
Если вы хотите больше контроля, используйте каркас Dependency Injection/Inversion of Control, например:
Имейте в виду, что все эти фреймворки имеют свои собственные мощные функции, но также добавляют сложность. Если вы чувствуете, что должны выбрать структуру, возьмите удобство обслуживания и обучаемость в качестве доминирующего требования.
Вот некоторая дополнительная документация по DI