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

发布于 2024-10-13 04:05:42 字数 274 浏览 3 评论 0原文

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

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

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

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

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

问候。

I have a Class called Repository for accessing (Read/Write to and from) Database.

The projects that require access to the database create an object of Repository and pass the connection string as a constructor parameter for the repository to work for that particular project.

I have few methods in the Repository that i want to be available only if certain connection strings are passed. I don't want them to be available if some different connection string is passed.

Is there any way I can accomplish that?

I have never used method header technique, can that help? if yes, how can i use it? if no, please let me know if there is any other way to achieve my goal.

Regards.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

穿透光 2024-10-20 04:05:42

您可以使用工厂方法模式来实现您的目标。
创建一个 RepositoryFactory 类,该类接收连接字符串并根据字符串的内容返回不同的存储库。

public class RepositoryFactory {

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

   }
}

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

You could use a factory method pattern to accomplish your goal.
Create a RepositoryFactory class that takes in the connection string and returns a different repository based upon the contents of the string.

public class RepositoryFactory {

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

   }
}

With this when someone wants a repository they call the GetRepository method.

緦唸λ蓇 2024-10-20 04:05:42

做的方式:

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

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

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

然后,在每个存储库方法中不允许,如果访问受限,则返回 null 或抛出异常或其他什么?

Sort of doing:

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

Is it possible that you could refactor your approach to create a new class:

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

Then, in each repository method not allowed, if limited access, return null or throw exception or something?

简单 2024-10-20 04:05:42

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

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

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

If you know in advance whether you'll need the extra methods, you could have a base version which doesn't support the extra methods, and a derived type which does. The constructor for the derived type could throw an exception if required information is not provided.

Using a factory method instead of a constructor would allow a base or fancy object to be constructed based upon the passed-in connection string; if you just have one factory method, though, you'll have to typecast the result if you want to use the extra methods.

The best approach may be to have a factory method for each defined type, with a guarantee that it will either return an object that's at least as good as the requested type or throw an exception if it can't. This approach would allow for future expansion in case more further-derived types become available.

是伱的 2024-10-20 04:05:42

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

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

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
{

}

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

If you want to limit the available methods, you could use a pattern like this.

Use the factory to get an instance like this:

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

And the code that makes this work is here

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
{

}

The downsides are, you get an explosion of Interfaces to control what methods are exposed. However, it is possible to cast between the various interfaces, but it avoids having to throw exceptions when a method isn't implemented.

放我走吧 2024-10-20 04:05:42

似乎没有一个完美的方法来做到这一点,但是我认为您的调用方法需要知道是否允许写入存储库,因为另一位海报已经指出方法的可用性是需要知道的编译时而不是运行时。

解决方案是创建两个界面,一种提供完整功能,另一种提供有限功能。

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

There doesn't seem to be a perfect way to do this however I think your calling method needs to know whether or not it is allowed to write to the Repository as another poster has stated the availability of methods is something that needs to be known at compile time rather than run time.

The solution would be to create two interfaces, one that offers full functionality and one that offers limited functionality.

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

    public interface IRead
    {
        object Read();
    }

Your Repository object then implements the top interface.

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

You can then have a class that determines if the connection string demands a read only repository or not and exposes 2 different methods to return the given type of interface (meaning you need to know the type at compile time).

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

You can then consume this as follows, seperating the points where you try to do actions that require full access by checking that you have a version of IRepository or of 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);
            }
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文