Могу ли я глобально настроить реализацию интерфейса для использования?

У меня есть интерфейс:

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