简体   繁体   English

C#中的实例类->静态类->实例类

[英]instance class->static class->instance class in C#

I have done a lot of reading on instance vs. static classes and have not found an answer to my question. 我已经大量阅读了实例和静态类,但没有找到我的问题的答案。 Are there any perils to instancing a different class in a static class that was referenced by an instance class? 在实例类引用的静态类中实例化其他类是否存在任何风险?

The current design I am working with is one in which instance classes call a static "Logger" method (passing a series of parameters) to log errors to a text file in the file system. 我正在使用的当前设计是其中实例类调用静态“ Logger”方法(传递一系列参数)以将错误记录到文件系统中的文本文件中的一种设计。 I am refactoring the static "Logger" method to instantiate a parameter class (which is just a series of properties and a few helper methods to return itself as XML or a string) and a DBLogger class to log the error to the database rather than the file system, passing the parameter class as the sole parameter. 我正在重构静态的“ Logger”方法以实例化一个参数类(它只是一系列属性和一些帮助程序方法以XML或字符串形式返回自身)和一个DBLogger类来将错误记录到数据库而不是数据库中。文件系统,将参数类作为唯一的参数传递。

This model worked well in my legacy VB6 code, in which the Logger class was instanced, not static. 该模型在我的旧版VB6代码中运行良好,其中Logger类是实例化的,而不是静态的。

But now in the .NET code I am not sure if I should make my 2 new classes (parameter and DBLogger) static, or just make the DBLogger static and instance the parameter class. 但是现在在.NET代码中,我不确定是否应该将我的2个新类(参数和DBLogger)设为静态,还是仅将DBLogger设为静态,并将实例作为参数类。 I am concerned about the potential for concurrency/multi-thread data issues with (or without) instances being created from a static class. 我担心从静态类创建(或不创建)实例的并发/多线程数据问题的可能性。 Am I right to be concerned or am I worrying about nothing? 我应该担心吗?还是我什么都不担心?

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

// all code truncated for illustration purposes

namespace ThisIs.A.Test
{
    //INSTANCE
    public class ErrorLogParameters
    {
        private int mThreadId = 0;
        private int mErrorNumber = 0;
        private string mServerDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");

        public int ThreadId
        {
            get { return mThreadId; }
            set { mThreadId = value; }
        }
        public int ErrorNumber
        {
            get { return mErrorNumber; }
            set { mErrorNumber = value; }
        }
        public string ServerDate
        {
            get { return mServerDate; }
        }
    }

    //INSTANCE
    public class ErrorLog
    {
        public void LogErrorToDatabase(ErrorLogParameters criteria)
        {
            //Log error to database here
        }
    }

    //STATIC - Instantiates INSTANCE of ErrorLogParameters and ErrorLog
    public class Logger
    {
        public static void WriteLog(string pstrObjectName, string pstrProcedureName, int plngErrNumber, string pstrErrDescription)
        {
            // create a new parameter object
            ErrorLogParameters objParameters = new ErrorLogParameters();

            // populate object properties
            objParameters.ErrorNumber = mlngErrNumber;
            objParameters.ThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;

            ErrorLog objErrorLog = new ErrorLog();

            objErrorLog.LogErrorToDatabase(objParameters);
        }
    }

    //INSTANCE - Invokes STATIC method
    public class SomeInstance 
    {
        private void ErrorHandler_Log(Exception exception, string procedureName, string additonalDescription, string stackTrace)
        {
            // call from instance class to static class
            Logger.WriteLog(mstrObjectName, procedureName, mlngErrNumber, mstrErrDescription);
        }
    }

}

No, that's absolutely fine - if you're creating an instance of any class within a method, it doesn't matter whether the class declaring that method is a static class or not. 不,那绝对很好-如果要在方法中创建任何类的实例,则声明该方法的类是否为静态类都没有关系。

Furthermore, unless you've got something "special" (eg a static variable counting the number of instances created) you're less likely to run into concurrency issues when creating new objects than when using existing objects. 此外,除非您有一些“特殊”的东西(例如,一个静态变量计算创建的实例数),否则与使用现有对象相比,创建对象时发生并发问题的可能性较小。 Basically, the tricky part of almost all concurrency is working out where mutable data is shared - it doesn't sound like you've got any here (although sample code would help to clarify that). 基本上,几乎所有并发中的棘手部分是确定共享可变数据的位置- 听起来好像没有什么在这里(尽管示例代码将有助于阐明这一点)。

I would use a combination of the provider and singleton pattern for this. 我将为此使用提供程序和单例模式的组合。

Create an abstract class called Logger. 创建一个称为Logger的抽象类。

  1. The Logger class contains abstract methods for writing to log. Logger类包含用于写入日志的抽象方法。 For example: 例如:
    • abstract void LogInfo(LogInfo info); 抽象void LogInfo(LogInfo info);
    • abstract void LogError(Exception exception); 抽象void LogError(Exception exception);
    • etc 等等
  2. The Logger class contains a private instance of Logger object. Logger类包含Logger对象的私有实例。
  3. The Logger class contains a static property that returns the private instance. Logger类包含一个返回私有实例的静态属性。
  4. The Logger class contains a static constructor that instantiate the private instance of Logger object. Logger类包含一个静态构造函数,该构造函数实例化Logger对象的私有实例。 You would probably use Reflection and instantiate the object based on the configuration. 您可能会使用Reflection并根据配置实例化该对象。
  5. Implement a FileLogger that inherits from the Logger object. 实现一个从Logger对象继承的FileLogger。 This logger writes to a file. 该记录器将写入文件。
  6. Implement a SQLLogger that inherits from the Logger object. 实现一个从Logger对象继承的SQLLogger。 This logger writes to a database. 该记录器将写入数据库。

Call the logger like so: 像这样调用记录器:

  • Logger.Instance.WriteInfo(info); Logger.Instance.WriteInfo(info);
  • Logger.Instance.WriteError(exception); Logger.Instance.WriteError(exception);

There are a few advantages of using this design: 使用此设计有一些优点:

  1. Your logging functionality is fully abstracted. 您的日志记录功能已完全抽象。 This completely decouple the logging callers from the code that writes the logs. 这将日志记录调用程序与编写日志的代码完全分离。 This allows you to write the log to any data stores. 这使您可以将日志写入任何数据存储。
  2. You can change which logger to use without compiling the code. 您可以更改要使用的记录器,而无需编译代码。 Just update the config file. 只需更新配置文件。
  3. Singleton guarantees thread-safety Singleton保证线程安全
  4. Testability. 可测试性。 You can write Mock tests against abstract classes. 您可以针对抽象类编写Mock测试。

Hope this helps. 希望这可以帮助。

There are no concurrency issues with static methods. 静态方法没有并发问题。

Static variables are a different matter. 静态变量是另一回事。

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

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