Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为接受参数/参数的类创建单例工厂_C#_Oop_Parameters_Singleton_Factory - Fatal编程技术网

C# 为接受参数/参数的类创建单例工厂

C# 为接受参数/参数的类创建单例工厂,c#,oop,parameters,singleton,factory,C#,Oop,Parameters,Singleton,Factory,首先,我是在一个网站上读到这篇文章的,它基本上告诉我,我根本不应该使用单例 最常见的情况是,在创建实例时,单例不允许指定任何参数——否则,对实例的第二个请求(但使用不同的参数)可能会有问题!(如果对于具有相同参数的所有请求都应访问相同的实例,则工厂模式更合适。) 因为我需要参数,同样的实例也需要相同的参数,所以我得出结论,我需要一个工厂模式 但是我在任何地方都找不到一个好的工厂模式实现 如果您发现任何好的带有参数的c#单例工厂模式实现,请告诉我 好的,我将尝试在这里非常具体。。。希望这能解释我的

首先,我是在一个网站上读到这篇文章的,它基本上告诉我,我根本不应该使用单例

最常见的情况是,在创建实例时,单例不允许指定任何参数——否则,对实例的第二个请求(但使用不同的参数)可能会有问题!(如果对于具有相同参数的所有请求都应访问相同的实例,则工厂模式更合适。)

因为我需要参数,同样的实例也需要相同的参数,所以我得出结论,我需要一个工厂模式

但是我在任何地方都找不到一个好的工厂模式实现

如果您发现任何好的带有参数的c#单例工厂模式实现,请告诉我

好的,我将尝试在这里非常具体。。。希望这能解释我的情况

最欢迎其他方法。我只是结合了很多实现——我的理解可能有偏差

所以我有一个类'a'。它是一个用于连接到数据库-数据库连接的类

连接需要4个参数&约束条件为:

  • 我需要有多个可能的连接-使用不同的数据库(参数不同)

  • 我只需要一个特定连接的实例-一个参数相同的单例(据我所知)

  • 我将需要一个工厂模型根据上述文章,并限制连接的数量,关闭后超时连接等

  • 在此基础上,我需要一个带有参数/参数的单例工厂。。。我想

    所以A班看起来像这样

    <which access modifier ?> Class A {
        private Class A(string hostname, string port, string username, string pw_hash) {
            //create a new instance with the specified parameters
        }
        //other methods on the connection
        protected void close() {
            //close the connection
        }
    }
    
    public class AFactory//should it inherit class A?? {
    
            private IList<A> connections = new List<A>();
            private AFactory()
            {
                //do something
            }
            private static readonly Lazy<AFactory> lazy
                = new Lazy<AFactory>(() => new AFactory());
    
            public static AFactory Instance { get { return lazy.Value; } }
    
            public A getA(string hostname, string service, string username, string pw_hash)
            {
                foreach (A a in A)
                {
                    if (a.hostname == hostname && a.service == service && a.username == username)
                        return a;
                }
                A d = new A(hostname, service, username, pw_hash);
                connections.Add(d);
                return d;
            }
    
    A类{
    私有类A(字符串主机名、字符串端口、字符串用户名、字符串pw_散列){
    //使用指定的参数创建新实例
    }
    //连接上的其他方法
    受保护的无效关闭(){
    //关闭连接
    }
    }
    公共类AFactory//是否应该继承类A??{
    私有IList连接=新列表();
    私人工厂
    {
    //做点什么
    }
    私有静态只读惰性
    =新懒惰(()=>新工厂());
    公共静态工厂实例{get{return lazy.Value;}}
    public A getA(字符串主机名、字符串服务、字符串用户名、字符串pw_散列)
    {
    foreach(A中的A)
    {
    if(a.hostname==hostname&&a.service==service&&a.username==username)
    返回a;
    }
    A d=新的A(主机名、服务、用户名、pw_散列);
    增加(d);
    返回d;
    }
    
    现在,只要类A构造函数是公共的,它就可以很好地工作——但它有点违背了单例的目的。 我需要做什么才能让代码正常工作

    对于指定的参数,我只需要一个类A实例。

    谢谢

    Indrajit

    试试这个:

    此接口从工厂初始值设定项公开,并包含公开的方法和属性

    public interface IDatabase
    {
        string ConnectionString { get; set; }
        IDataReader ExecuteSql(string sql);
    }
    
    Factory基抽象类,在该类中可以对不同类型的数据库工厂执行通用功能

    public abstract class FactoryBase
    {
        public FactoryBase() { }
    
        public abstract IDatabase GetDataLayer();
    }
    
    包含调用的具体sql类。请查看ExecuteSql方法。该连接在命令中是自包含的,因此您不必担心打开、关闭和处理它

    public class SQL : IDatabase
    {
        private string m_ConnectionString = string.Empty;
    
        public string ConnectionString
        {
            get { return m_ConnectionString; }
            set { m_ConnectionString = value; }
        }
    
        public IDataReader ExecuteSql(string sql)
        {
            using (var command = new SqlCommand(sql, new SqlConnection(ConnectionString)) { CommandType = CommandType.Text, CommandText = sql, CommandTimeout = 0 })
            {
                if (command.Connection.State != ConnectionState.Open) command.Connection.Open();
                return command.ExecuteReader();
            }
        }
    }
    
    创建Sql具体类实例的Sql工厂类

    class SQLFactory : FactoryBase
    {
        public override IDatabase GetDataLayer()
        {
            return new SQL();
        }
    }
    
    开发人员用于传入工厂类型并返回IDatabase的工厂初始值设定项类

    public static class FactoryInitializer
    {
        public static IDatabase LoadFactory<T>(string connectionstring) where T : FactoryBase, new()
        {
            var factory = new T();
            var data = factory.GetDataLayer();
            data.ConnectionString = connectionstring;
            return data;
        }
    }
    
    公共静态类FactoryInitializer
    {
    公共静态IDatabase LoadFactory(string connectionstring),其中T:FactoryBase,new()
    {
    var factory=newt();
    var data=factory.GetDataLayer();
    data.ConnectionString=连接字符串;
    返回数据;
    }
    }
    
    然后将其用作:

    var factory = FactoryInitializer.LoadFactory<SQLFactory>(connectionString);
    factory.ExecuteSql("SELECT ...");
    
    var-factory=FactoryInitializer.LoadFactory(connectionString);
    ExecuteSql(“选择…”);
    

    然后,您可以创建一个OracleFactory和一个Oracle混凝土类,并以相同的方式使用它。

    所以我已经这样做了,它可以工作了……您能告诉我它是否正确。它是否线程安全

    public Class A 
    {
        private A(string hostname, string port, string username, string pw_hash) {
            //create a new instance with the specified parameters
        }
        //other methods on the connection
        protected void close() {
            //close the connection
        }
        public class AFactory 
        {
        private IList<A> connections = new List<A>();
        private AFactory()
        {
            //do something
        }
        private static readonly Lazy<AFactory> lazy
            = new Lazy<AFactory>(() => new AFactory());
    
        public static AFactory Instance { get { return lazy.Value; } }
    
        public A getA(string hostname, string service, string username, string pw_hash)
        {
            foreach (A a in connections)
            {
                if (a.hostname == hostname && a.service == service && a.username == username)
                    return a;
            }
            A d = new A(hostname, service, username, pw_hash);
            connections.Add(d);
            return d;
        }
        }
    
    }
    

    此实现是否存在明显错误?

    工厂用于生成对象而不是管理对象。我认为DB连接管理器更适合您的情况。您可以将管理器声明为单例。对于单个连接,您可以使用内部类/结构

    请参见以下示例:

    class DBConnectionManager
    {        
        struct Connection
        {
          public string Hostname;
          public string ServerName;
          public string UserName;
          public string Password;
    
          public void Connect()
          {
          }
    
          public void Close()
          {
          } 
        }
    
        private static s_instance;
        public static DBConnectionManager Instance
        {
            get {return s_instance; }
        }
    
        private List<Connection> m_connections;
    
        public Connection GetConnection(string hostname, string serverName, string userName, string password)
        {
            // if already exist in m_connections
            // return the connection
            // otherwise create new connection and add to m_connections    
        }
    
        public void CloseConnection(string hostname, string serverName, string userName, string password)
        {
            // if find it in m_connections
            // then call Close()
        }
    
        public void CloseAll()
        {
            //
        }        
    } 
    
    classdbconnectionmanager
    {        
    结构连接
    {
    公共字符串主机名;
    公共字符串ServerName;
    公共字符串用户名;
    公共字符串密码;
    公共void Connect()
    {
    }
    公众假期结束()
    {
    } 
    }
    私有静态s_实例;
    公共静态DBConnectionManager实例
    {
    获取{return s_instance;}
    }
    私有列表m_连接;
    公共连接GetConnection(字符串主机名、字符串服务器名、字符串用户名、字符串密码)
    {
    //如果m_连接中已存在
    //返回连接
    //否则,创建新连接并添加到m_连接
    }
    public void CloseConnection(字符串主机名、字符串服务器名、字符串用户名、字符串密码)
    {
    //如果在m_连接中找到它
    //然后调用Close()
    }
    公共空间关闭所有()
    {
    //
    }        
    } 
    
    您可以尝试以下方法:

    public static class Singlett<Param,T>
       where T : class
    {
        static volatile Lazy<Func<Param, T>> _instance;
        static object _lock = new object();
    
        static Singlett()
        {
        }
    
        public static Func<Param, T> Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new Lazy<Func<Param, T>>(() =>
                    {
                        lock (Singlett<Param,T>._lock)
                        {
                            try
                            {
                                ConstructorInfo constructor = null;
                                Type[] methodArgs = { typeof(Param) };                                
                                constructor = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, methodArgs, null);// Binding flags excludes public constructors.
                                if (constructor == null)
                                {
                                    constructor = typeof(T).GetConstructor(BindingFlags.Public, null, methodArgs, null);
                                    if (constructor == null)
                                        return delegate(Param o) { return (T)Activator.CreateInstance(typeof(T), new object[] { o }); };
                                }
                                return delegate(Param o) { return (T)constructor.Invoke(new object[] { o }); };
                            }
                            catch (Exception exception)
                            {
                                throw exception;
                            }
                        }
                    });
                }
                return _instance.Value;
            }
        }
    }
    
    你可以写:

    int i = 10;
    MyClass class = Singlett<int,MyClass>.Instance(i);
    
    inti=10;
    MyClass=Singlett.Instance(i);
    
    这个问题与Java无关。为什么您需要工厂来创建单例对象?
    只要a类构造函数是公共的
    您就可以将
    a
    作为工厂的内部类来实现
    int i = 10;
    MyClass class = new MyClass(i);
    
    int i = 10;
    MyClass class = Singlett<int,MyClass>.Instance(i);