获取基类的相同实例

时间:2016-05-03 14:21:13

标签: c# singleton

我有两节课:

public class DefaultMachineSettings : MachineSettings
{
    private static DefaultMachineSettings instance;

    private DefaultMachineSettings() { }

    public static DefaultMachineSettings getInstance()
    {
        if (instance == null)
            instance = new DefaultMachineSettings();

        return instance;
    }

    public static void destroyInstance()
    {
        instance = null;
    }
}

第二课:

public class Sani80100Settings : MachineSettings
{
    private static Sani80100Settings instance;

    private Sani80100Settings()
    {
        setDefaultMachineXML(true);
    }

    public static Sani80100Settings getInstance()
    {
        if (instance == null)
            instance = new Sani80100Settings();
        return instance;
    }

    public void setDefaultMachineXML(Boolean overrideValue)
    {
        Dictionary<String, String> defaultXML = new Dictionary<string, string>();
        defaultXML.Add("WZ1_Beschreibung", "Trennwerkzeug");
        defaultXML.Add("WZ1_Offset", "0");
        defaultXML.Add("WZ1_WirkungsbereichLinks", "2.5");
        defaultXML.Add("WZ1_WirkungsbereichRechts", "2.5");

        defaultXML.Add("WZ2_Beschreibung", "Aufzugband/Omega");
        defaultXML.Add("WZ2_Offset", "-118");
        defaultXML.Add("WZ2_WirkungsbereichLinks", "0");
        defaultXML.Add("WZ2_WirkungsbereichRechts", "0");

        defaultXML.Add("WZ3_Beschreibung", "Doppelloch Abspannung");
        defaultXML.Add("WZ3_Offset", "-250.1");
        defaultXML.Add("WZ3_WirkungsbereichLinks", "0");
        defaultXML.Add("WZ3_WirkungsbereichRechts", "0");

        defaultXML.Add("WZ4_Beschreibung", "Zusätzliche Abspannung");
        defaultXML.Add("WZ4_Offset", "-380");
        defaultXML.Add("WZ4_WirkungsbereichLinks", "0");
        defaultXML.Add("WZ4_WirkungsbereichRechts", "0");

        defaultXML.Add("Vorschub60", "100");
        defaultXML.Add("LamellenlaengeSoll60", "1998.5");
        defaultXML.Add("LamellenlaengeIst60", "2000");

        defaultXML.Add("Vorschub80", "100");
        defaultXML.Add("LamellenlaengeSoll80", "2000.5");
        defaultXML.Add("LamellenlaengeIst80", "2000");

        defaultXML.Add("Vorschub100", "100");
        defaultXML.Add("LamellenlaengeSoll100", "2003");
        defaultXML.Add("LamellenlaengeIst100", "2000");

        config.setDefaultXml(defaultXML, overrideValue);
    }
}

基类:

 public class MachineSettings : SettingsBase
{

    protected MachineSettings() : base()
    {
        ClientSettings clientSettings = ClientSettings.getInstance();

        String path = ConfigPath +  "machines\\";

        if (!Directory.Exists(path))
            Directory.CreateDirectory(path);

        Machine.Name machineName;

        //Hier wird überprüft, ob die SAP Maschine ein Äquivalent in Apertum hat um die gleiche Konfigurationsdatei zu verwenden. 
        switch (clientSettings.MachineName)
        {
            case Machine.Name.SANI8_10:
                machineName = Machine.Name.A7660_01;
                break;
            default:
                machineName = clientSettings.MachineName;
                break;
        }

        String fileName = machineName + "_" + Environment.UserName + ".xml";

        restoreTempConfig("machines\\" + fileName);
        config = new ConfigXml(path + fileName);

        setDefaultXML();
    }
}

SettingsBase

public abstract class SettingsBase
{
    public ConfigXml config;

    public const String CHARACTERISTIC_PREFIX = "#c#";

    private readonly static String NetworkPath = @"\\dc2\Programmdaten$\" + Environment.MachineName.ToUpper() + @"\Maschinenclient\";
    private readonly static String TempPath = Path.GetTempPath() + @"\Maschinenclient\";

    public String ConfigPath;

    public static Boolean TEMPPATHSAVING = false;

    public SettingsBase()
    {
        if (!Directory.Exists(NetworkPath))
        {
            try
            {
                Directory.CreateDirectory(NetworkPath);
                ConfigPath = NetworkPath;
            }
            catch (UnauthorizedAccessException)
            {
                ConfigPath = TempPath;
            }
            catch
            {
                ConfigPath = TempPath;
            }
        }
        else
        {
            if (WriteAccess(NetworkPath))
                ConfigPath = NetworkPath;
            else
                ConfigPath = TempPath;
        }


        if (ConfigPath == TempPath)
        {
            if (!Directory.Exists(TempPath))
                Directory.CreateDirectory(TempPath);

            TEMPPATHSAVING = true;
        }
        else
            TEMPPATHSAVING = false;
    }

    public void restoreTempConfig(String fileName)
    {
        if (ConfigPath == NetworkPath)
        {
            if (File.Exists(TempPath + fileName))
            {
                if (!File.Exists(NetworkPath + fileName))
                    File.Copy(TempPath + fileName, NetworkPath + fileName, false);

                File.Delete(TempPath + fileName);
            }
        }

    }

    private Boolean WriteAccess(String path)
    {
        try
        {
            path = path + DateTime.Now.ToString("yyyyMMddHHmmssffff") + Environment.MachineName.ToUpper() + Environment.UserName + ".access";
            FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);

            using (StreamWriter streamWriter = new StreamWriter(fileStream))
            {
                streamWriter.WriteLine("ACCESS GRANTED");
            }

            fileStream.Close();

            File.Delete(path);

            return true;
        }
        catch (UnauthorizedAccessException)
        {
            return false;
        }
        catch
        {
            return false;
        }
    }
}

是否有可能只有一个基类MachineSettings的实例?

这意味着DefaultMachineSettingsSani80100Settings应使用相同的MachineSettings实例

我google了很多,但没有得到线索。

有人知道解决方案吗?

招呼

1 个答案:

答案 0 :(得分:4)

如果您要使用继承,那么DefaultMachineSettingsSani80100Settings的每个实例都将继承自己的MachineSettings

如果你需要有两个具有相同base实例的单例实例(来自不同的类),那么你需要使用聚合,而不是继承。

类似的东西:

public class FirstClass
{
    private static FirstClass instance;

    private FirstClass(BaseClass baseInstance) { /* store baseInstance somewhere */ }

    public static FirstClass getInstance()
    {
        if (instance == null)
            instance = new FirstClass(BaseClass.getInstance());

        return instance;
    }
}

public class SecondClass
{
    private static SecondClass instance;

    private SecondClass(BaseClass baseInstance) { /* store baseInstance somewhere */ }

    public static SecondClass getInstance()
    {
        if (instance == null)
            instance = new Second(BaseClass.getInstance());

        return instance;
    }
}

public class BaseClass 
{
    private static BaseClass instance;

    private BaseClass() {}

    public static BaseClass getInstance()
    {
        if (instance == null)
            instance = new BaseClass();

        return instance;
    }
}

在这种情况下,您将无法使用protected中的任何BaseClass成员。

更新1

使用Autofac的示例:

using System;
using Autofac;

namespace DemoApp
{
  public class Program
  {
    private static IContainer Container { get; set; }

    static void Main(string[] args)
    {
      var builder = new ContainerBuilder();
      // register your base class
      builder.RegisterType<BaseClass>() // register base class
             .AsSelf()                  // register as `BaseClass` (without any interfaces)
             .SingleInstance();         // register as a singleton

      // register all your child classes
      builder.RegisterType<FirstClass>()
             .AsSelf()                  
             .SingleInstance();
      builder.RegisterType<SecondClass>()
             .AsSelf()                  
             .SingleInstance();

      // or you can do the following
      // get the assembly
      var dataAccess = Assembly.GetExecutingAssembly();

      // and register all classes which ends with 'Settings' as singletons
      builder.RegisterAssemblyTypes(dataAccess)
             .Where(t => t.Name.EndsWith("Settings"))
             .AsSelf()
             .SingleInstance();   

      Container = builder.Build();

      // The DoWorkmethod is where we'll make use
      // of our dependency injection.
      DoWork();
    }

    public static void WriteDate()
    {
        // Create the scope, resolve your FirstClass,
        // use it, then dispose of the scope.
        using (var scope = Container.BeginLifetimeScope())
        {
            var firstClass = scope.Resolve<FirstClass>();
            firstClass.SomeMethodOrWhatever();
        }
    }
  }
}

希望它会有所帮助。