【问题标题】:Availability of Methods on the basis of Constructor基于构造函数的方法可用性
【发布时间】:2011-01-19 16:49:02
【问题描述】:

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

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

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

有什么办法可以做到吗?

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

问候。

【问题讨论】:

  • 感谢您的所有建议,我认为对此没有“一个”答案...但我发现 FactoryRepository/Interface 建议更适用,我想我会同意...谢谢再一次……

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


【解决方案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 方法。

【讨论】:

  • 问题是,您返回的是相同的界面。那么无效方法应该抛出 NotImplementedException() 吗?
  • 是的,这是此方法的限制。您可以让调用者转换为他们想要的实例。
【解决方案2】:

做了什么:

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

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

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

那么,在每个repository方法不允许,如果限制访问,返回null或者抛出异常什么的?

【讨论】:

  • 可能是它的一个变体,而不是 IsLimitedAccess,而是支持命名操作的 IList<string>。如果可用操作集因连接而异,单个标志可能不够灵活?
  • 是的,没错,但如果不了解问题的所有细节,就很难判断它是否需要深入到那个深度......
【解决方案3】:

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

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

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

【讨论】:

    【解决方案4】:

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

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

    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
    {
    
    }
    

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

    【讨论】:

      【解决方案5】:

      似乎没有一个完美的方法来做到这一点,但是我认为你的调用方法需要知道它是否被允许写入存储库,因为另一位发帖人表示方法的可用性是需要的在编译时而不是运行时知道。

      解决方案是创建两个接口,一个提供完整功能,一个提供有限功能。

          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 only 的版本来区分您尝试执行需要完全访问权限的操作的点。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-05
        • 1970-01-01
        • 2018-06-30
        相关资源
        最近更新 更多