Наличие методов на основе конструктора - PullRequest
0 голосов
/ 19 января 2011

У меня есть класс с именем Repository для доступа к базе данных (чтение / запись в и из).

Проекты, которым требуется доступ к базе данных, создают объект репозитория и передают строку соединения в качестве параметра конструктора для репозитория для работы с этим конкретным проектом.

У меня есть несколько методов в репозитории, которые я хочу быть доступными, только если переданы определенные строки подключения. Я не хочу, чтобы они были доступны, если передана какая-то другая строка подключения.

Есть ли способ, которым я могу это сделать?

Я никогда не использовал метод заголовка метода, это может помочь? если да, как я могу его использовать? если нет, пожалуйста, дайте мне знать, если есть какой-либо другой способ достичь моей цели.

Привет.

Ответы [ 5 ]

1 голос
/ 19 января 2011

Вы можете использовать шаблон фабричного метода для достижения своей цели.
Создайте класс RepositoryFactory, который принимает строку подключения и возвращает другой репозиторий на основе содержимого строки.

public class RepositoryFactory {

   public IRepository GetRepository(string connection) 
   {
        if(SomeTestOnConnect(connection))
            return new SimpleRepository(connection);
        else
           return new FullRepository(connection);

   }
}

При этом, когда кто-то хочет получить хранилище, он вызывает метод GetRepository.

0 голосов
/ 19 января 2011

Кажется, нет идеального способа сделать это, однако я думаю, что ваш вызывающий метод должен знать, разрешено ли ему писать в репозиторий, так как другой автор заявил, что доступность методов - это то, что нужнобыть известным во время компиляции, а не во время выполнения.

Решение будет состоять в том, чтобы создать два интерфейса, один с полной функциональностью, а другой с ограниченной функциональностью.

    public interface IRepository : IRead
    {
        void Write(object o);
    }

    public interface IRead
    {
        object Read();
    }

Тогда ваш объект репозиторияреализует верхний интерфейс.

    public class Repository : IRepository
    {
        private readonly string _connectionString;
        public Repository(string connectionString)
        {
            _connectionString = connectionString;
        }
        public object Read()
        {
           // Do stuff
        }

        public void Write(object o)
        {
           // Do stuff
        }
    }

После этого вы можете иметь класс, который определяет, требует ли строка подключения доступ к хранилищу только для чтения, и предоставляет 2 различных метода для возврата интерфейса данного типа (то есть вам нужнознать тип во время компиляции).

    public static class RepositoryFactory
    {
        public static bool ConnectionStringIsReadOnly(string connectionString)
        {
            return connectionString.Contains("user=hacker");
        }

        public static IRead GetReadOnlyRepository(string connectionString)
        {
            return new Repository(connectionString);
        }

        public static IRepository GetRepository(string connectionString)
        {
            if (ConnectionStringIsReadOnly(connectionString)) throw new ArgumentException(@"Given connectionString is not allowed full repository access", "connectionString");
            return new Repository(connectionString);
        }
    }

Затем вы можете использовать это следующим образом, разделяя точки, в которых вы пытаетесь выполнить действия, требующие полного доступа, проверяя, что у вас есть версия IRepository или IReadтолько.

    public class Program
    {
        public void ConsumeRepository(string connectionString)
        {
            IRead reader = null;
            IRepository repository = null;
            if (RepositoryFactory.ConnectionStringIsReadOnly(connectionString))
                reader = RepositoryFactory.GetReadOnlyRepository(connectionString);
            else
            {
                repository = RepositoryFactory.GetRepository(connectionString);
                reader = repository;
            }

            object o = reader.Read();

            // do something with o

            // if allowed then write o to repository
            if (repository != null)
            {
                repository.Write(o);
            }
        }
    }
0 голосов
/ 19 января 2011

Если вы хотите ограничить доступные методы, вы можете использовать шаблон, подобный этому.

Используйте фабрику, чтобы получить экземпляр, подобный этому:

var repo = RepositoryFactory.Resovle<IFullRepository>("connection string");

И код, который делаетэта работа здесь

public class RepositoryFactory
{
    public static T Resovle<T>(string connection) where T: IRepository
    {
        IRepository instance = new Repository(connection);
        return (T)instance;
    }

    private class Repository : IFullRepository
    {
        private string _connection;

        public Repository(string connection)
        {
            _connection = connection;
        }

        public object Get(int id)
        {
            // select
        }

        public void Save(object o)
        {
            // upate
        }

        public void Create(object o)
        {
            // create
        }

        public void CustomMethodOne()
        {
            // do something specialized
        }

        public void CustomMethodTwo()
        {
            // do something specialized
        }
    }
}

public interface IRepository
{
    object Get(int id);
    void Save(object o);
    void Create(object o);
}

public interface IRepositoryProjectOne: IRepository
{
    void CustomMethodOne();
}

public interface IRepositoryProjectTwo: IRepository
{
    void CustomMethodTwo();
}

public interface IFullRepository: IRepositoryProjectOne, IRepositoryProjectTwo
{

}

Недостатки: вы получаете взрыв Интерфейсов, чтобы контролировать, какие методы подвергаются.Тем не менее, существует возможность преобразования между различными интерфейсами, но при этом не требуется создавать исключения, когда метод не реализован.

0 голосов
/ 19 января 2011

Если вы заранее знаете, нужны ли вам дополнительные методы, у вас может быть базовая версия, которая не поддерживает дополнительные методы, и производный тип, который делает. Конструктор для производного типа может вызвать исключение, если требуемая информация не указана.

Использование фабричного метода вместо конструктора позволило бы создать базовый или причудливый объект на основе переданной строки соединения; тем не менее, если у вас есть только один фабричный метод, вам придется ввести результат, если вы хотите использовать дополнительные методы.

Наилучший подход может заключаться в том, чтобы иметь метод фабрики для каждого определенного типа с гарантией, что он либо возвратит объект, который по крайней мере так же хорош, как запрошенный тип, либо выдает исключение, если не может. Этот подход позволил бы в будущем расширяться в случае, если станет доступно больше дополнительных производных типов.

0 голосов
/ 19 января 2011

В некотором роде:

if (_connection == "XYZ")
   throw new InvalidOperationException();

Возможно ли, что вы могли бы реорганизовать свой подход для создания нового класса:

public class ConnectionInfo
{
   public string ConnectionString { get; set; }
   public bool IsLimitedAccess { get; set; }
}

Тогда, в каждом методе хранилища не допускается, еслиограниченный доступ, возврат нуля или выдача исключения или что-то еще?

...