基于构造函数的方法的可用性

时间:2011-01-19 16:49:02

标签: c# asp.net .net-3.5 ado.net

我有一个名为Repository的类,用于访问(读/写)数据库。

需要访问数据库的项目创建一个Repository对象,并将连接字符串作为构造函数参数传递给存储库,以便为该特定项目工作。

我在Repository中有几个方法只有在传递某些连接字符串时才能使用。如果传递了一些不同的连接字符串,我不希望它们可用。

我有什么方法可以做到这一点吗?

我从未使用过方法头技术,这有帮助吗?如果是的话,我该如何使用它?如果没有,请告诉我是否有其他方法可以实现我的目标。

问候。

5 个答案:

答案 0 :(得分:1)

您可以使用factory method pattern来实现目标 创建一个RepositoryFactory类,它接受连接字符串并根据字符串的内容返回不同的存储库。

public class RepositoryFactory {

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

   }
}

当有人想要一个存储库时,他们会调用GetRepository方法。

答案 1 :(得分:0)

做的事情:

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

您是否有可能重构您创建新类的方法:

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

然后,在每个存储库方法不允许的情况下,如果访问受限,返回null或抛出异常或什么?

答案 2 :(得分:0)

如果您事先知道是否需要额外的方法,则可能有一个不支持额外方法的基本版本,以及一个派生类型。如果未提供所需信息,派生类型的构造函数可能会抛出异常。

使用工厂方法而不是构造函数将允许基于传入的连接字符串构造基础或花式对象;但是,如果您只有一个工厂方法,那么如果您想使用额外的方法,则必须对结果进行类型转换。

最好的方法可能是为每个定义的类型提供一个工厂方法,并保证它将返回一个至少与请求的类型一样好的对象,否则抛出异常。如果有更多进一步派生的类型可用,这种方法将允许未来的扩展。

答案 3 :(得分:0)

如果要限制可用方法,可以使用这样的模式。

使用工厂获取这样的实例:

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
{

}

缺点是,您获得了大量接口来控制暴露的方法。但是,可以在各种接口之间进行转换,但它避免了在未实现方法时抛出异常。

答案 4 :(得分:0)

似乎没有一种完美的方法可以做到这一点但是我认为你的调用方法需要知道它是否被允许写入存储库,因为另一张海报已经声明方法的可用性是需要的在编译时而不是运行时知道。

解决方案是创建两个接口,一个提供全部功能,另一个提供有限的功能。

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

    public interface IRead
    {
        object Read();
    }

您的Repository对象然后实现顶部接口。

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