how do I set the current class to the return types

2019-08-03 02:33发布

I have this class:

using System.IO;
using System.Xml.Serialization;

    namespace ssscc.Settings
    {
      public class AppSettings
      {
        private string _companyName;
        public string CompanyName
        {
          set { _companyName = value; }
          get
          {
            if (string.IsNullOrWhiteSpace(_companyName))
            {
              LoadSettings();
            }
            return _companyName;
          }
        }

        private string _companyPhone;
        public string CompanyPhone
        {
          set
          {

            _companyPhone = value;
          }
          get
          {
            if (string.IsNullOrWhiteSpace(_companyPhone))
            {
              LoadSettings();
            }
            return _companyPhone;
          }
        }

        private string GetSettingsFile()
        {
          var exePath = System.Windows.Forms.Application.StartupPath;
          var sharedDirectory = Path.Combine(exePath, "shared");
          var settingsDirectory = Path.Combine(sharedDirectory, "settings");
          var settingsFile = Path.Combine(settingsDirectory, "ssscc.xml");

          if (!Directory.Exists(sharedDirectory))
          {
            Directory.CreateDirectory(sharedDirectory);
          }

          if (!Directory.Exists(settingsDirectory))
          {
            Directory.CreateDirectory(settingsDirectory);
          }

          return settingsFile;
        }

        internal void SaveSettings(AppSettings settings)
        {
          var serializer = new XmlSerializer(typeof(AppSettings));
          using (var stream = File.OpenWrite(GetSettingsFile()))
          {
            serializer.Serialize((Stream) stream, (object) settings);
          }
        }

        internal void LoadSettings()
        {
          if (!File.Exists(GetSettingsFile()))
          {
            return;
          }

          var serializer = new XmlSerializer(typeof(AppSettings));
          using (var stream = File.OpenRead(GetSettingsFile()))
          {
            var appsetting = (AppSettings) serializer.Deserialize(stream);
            CompanyPhone = appsetting.CompanyPhone;
            CompanyName = appsetting.CompanyName;
          }
        }

      }
    }

My question is about this code:

   var appsetting = (AppSettings) serializer.Deserialize(stream);
    CompanyPhone = appsetting.CompanyPhone;
    CompanyName = appsetting.CompanyName;

I am pretty sure there is a way to return the appsettings directly to the class that contains the method so I do not have to loop through each property such as this:

    CompanyPhone = appsetting.CompanyPhone;
    CompanyName = appsetting.CompanyName;

Can I assign the properties directly without having to maintain this code?

标签: c# class
2条回答
2楼-- · 2019-08-03 03:24

Do you really need to have lazy-loading in here, if not, make your methods explicitly:

public class AppSettings
{
    private static readonly XmlSerializer Serializer 
                  = new XmlSerializer(typeof(AppSettings));

    public string CompanyName { get; set; }
    public string CompanyPhone { set; get; }

    private static string GetSettingsFile()
    {
        return null;
    }

    public static void SaveSettings(AppSettings settings)
    {
        using (var stream = File.OpenWrite(GetSettingsFile()))
            Serializer.Serialize(stream, settings);
    }

    internal static AppSettings LoadSettings()
    {
        if (!File.Exists(GetSettingsFile()))
            return null;

        object appsetting = null;

        using (var stream = File.OpenRead(GetSettingsFile()))
            appsetting = Serializer.Deserialize(stream);

        return appsetting as AppSettings;
    }
}

Do you can use:

var setting = AppSettings.LoadSettings();

and:

AppSettings.SaveSettings(setting);

Please note in here, creating XmlSerializer everytime will get the memory leak,

The XmlSerializer constructor will generate a pair of classes derived from XmlSerializationReader and XmlSerializationWriter by analyzing the Person class using reflection. It will create temporary C# files, compile the resulting files into a temporary assembly, and finally load that assembly into the process. Code gen like this is also relatively expensive. So the XmlSerializer caches the temporary assemblies on a per-type basis. This means that the next time an XmlSerializer for the Person class is created, the cached assembly is used rather than a new one generated.

Therefore, you should keep XmlSerializer as static.

查看更多
一纸荒年 Trace。
3楼-- · 2019-08-03 03:28

You are getting a new instance of AppSettings while deserializing from file. You may use it, can't you? Try to replace LoadSettings with a static factory method like this:

internal static AppSettings GetInstance()
{
    if (!File.Exists(GetSettingsFile()))
        return null;

    var serializer = new XmlSerializer(typeof(AppSettings));
    using (var stream = File.OpenRead(GetSettingsFile()))
        return (AppSettings)serializer.Deserialize(stream);
}

while to save your settings, you have no need to pass the settings object as an argument. I guess the following code should do the job:

internal void SaveSettings()
{
    var serializer = new XmlSerializer(typeof(AppSettings));
    using (var stream = File.OpenWrite(GetSettingsFile()))
        serializer.Serialize((Stream)stream, this);
}

Use the factory GetInstance method to initialize settings (well, as an example):

var s = AppSettings.GetInstance();
if (s == null)
{
    s = new AppSettings
    {
        CompanyName = "MyCompany",
        CompanyPhone = "######"
    };
    s.SaveSettings();
}

P.S.: if properties getters and setters have no additional logic (LoadSettings method no longer exists), you could use auto-properties:

public string CompanyName { get; set; }

public string CompanyPhone { get; set; }

and GetSettingsFile may be declared as static, as it does not operate any of the instance class members:

private static string GetSettingsFile()
{
    //...
    return settingsFile;
}
查看更多
登录 后发表回答