简体   繁体   English

为同一个名称空间扩展C#类?

[英]Extending a C# class for the same namespace?

How may I easily extend a C# class tohave an additional class for the same use? 我如何轻松地将C#类扩展为具有相同用途的其他类? It may sound a bit weird but consider this: 听起来可能有些怪异,但请考虑以下几点:

ConfigurationManager is the main class in the Habbo_Hotel.assets namespace, and I've got two global variables called configuration (general) and configDatabase (database). ConfigurationManagerHabbo_Hotel.assets命名空间中的主要类,我有两个全局变量,分别称为configuration (常规)和configDatabase (数据库)。 This is how I'm using the general settings through the Program class: 这就是我通过Program类使用常规设置的方式:

assets.ConfigurationManager configurationManager = new 
assets.ConfigurationManager();
configurationManager.Init();

configurationManager.debug

Now, this is the simpliest use of the class, now I want to be able to call something like: 现在,这是该类的最简单的用法,现在我希望能够调用以下内容:

configurationManager.database.hostname

Instead of having a function called configurationManager.databaseHostname . 而不是使用名为configurationManager.databaseHostname的函数。 If this is possible to do, how can I extend the C# class to have a .database class in its origin? 如果可以这样做,如何将C#类扩展为在其原始位置具有.database类? Thanks. 谢谢。

using System;
using System.Xml;
using System.Collections.Generic;

namespace Habbo_Hotel.assets
{
    public class ConfigurationManager
    {
        private static Dictionary<string, string> configuration = new Dictionary<string, string>();
        private static Dictionary<string, string> configDatabase = new Dictionary<string, string>();

        public int debug
        {
            get { return Int32.Parse(configuration["debug"]); }
            set { configuration["debug"] = value.ToString(); }
        }

        public void Init()
        {

            try
            {
                XmlDocument xml = new XmlDocument();
                xml.Load("configuration.xml");

                try
                {
                    //general
                    configuration.Add("debug", xml.SelectSingleNode("settings/general/debug").InnerXml);

                    //database
                    configDatabase.Add("hostname", xml.SelectSingleNode("settings/database/hostname").InnerXml);
                    configDatabase.Add("username", xml.SelectSingleNode("settings/database/username").InnerXml);
                    configDatabase.Add("password", xml.SelectSingleNode("settings/database/password").InnerXml);
                    configDatabase.Add("database", xml.SelectSingleNode("settings/database/database").InnerXml);
                }
                catch (Exception exception)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Uncaught exception: " + exception.Message);
                    Console.ResetColor();
                }

            }
            catch (Exception exception)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Uncaught exception: " + exception.Message);
                Console.ResetColor();
            }
        }
    }
}

Ok, so following discussion with you in chat I've established that your request for a 'class' called database is a red herring. 好的,因此在聊天中与您讨论之后,我确定您对名为“数据库”的“类”的请求是一个红鲱鱼。 You simply want to be able to access the hostname via .database.hostname . 您只希望能够通过.database.hostname访问主机名。

Since you've gone as far as providing us with your implementation now my first response is that you probably shouldn't be saving those properties in dictionaries - this isn't a very object oriented way of doing things. 既然您已经竭尽全力为我们提供了实现,那么我的第一个回答是您可能不应该将这些属性保存在字典中-这不是一种非常面向对象的处理方式。 So with that in mind you could: 因此,考虑到这一点,您可以:

1. Create a "Database" type (a new class) that encapsulates the database configuration. 1.创建封装数据库配置的“数据库”类型(新类)。 Instead of saving the settings in the Dictionary during initialisation, instantiate a new "Database" object and save the settings in that. 实例化一个新的“数据库”对象并在其中保存设置,而不是在初始化期间将其保存在字典中。 Then simply return the Database object in the property 然后只需在属性中返回Database对象

public class Database {
    public string HostName { get; set; }
    // and the rest
}

public class ConfigurationManager {
    public Database Database { get; private set; }
    public void Init() {
       // The rest of the Init code
       Database = new Database { 
           HostName = xml.SelectSingleNode("settings/database/hostname").InnerXml
       }
    }
}

However, if you really must retain the dictionary implementation you could 但是,如果您确实必须保留字典实现,则可以

2. Implement the HostName property on the ConfigurationManager class, have the ConfigurationManager class implement two different interfaces, have a property called Database that returns this 2.在ConfigurationManager类上实现HostName属性,让ConfigurationManager类实现两个不同的接口,并具有一个名为Database的属性,该属性返回

public interface IConfigurationManager {
    IConfigurableDatabase Database { get; }
    void Init();
}

public interface IConfigurableDatabase {
   string HostName { get; }
   // And the rest
}

public class ConfigurationManager 
    : IConfigurationManager, IConfigurableDatabase  {
    private static Dictionary<string, string> configDatabase = new Dictionary<string, string>();
    IConfigurableDatabase Database => this;

    public HostName {
        get => configDatabase["hostname"];
        set => configDatabase["hostname"] = value
    }
}

However this is needlessly complicated and you really should be using option 1 . 但是,这不必要地复杂,您实际上应该使用选项1

PS: PS:

By the way, in the implementation of your Init method, you only need one try/catch block. 顺便说一下,在实现Init方法时,您只需要一个try / catch块。 If you remove the inner block, the outer one will do the job of the inner one. 如果卸下内部模块,则外部模块将完成内部模块的工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM