正在更新C#中引用的对象

本文关键字:引用 对象 更新 | 更新日期: 2023-09-27 18:26:21

我的项目中有一个用于设置的singleton对象,我通过引用传递它。现在,我在应用程序中使用MVVM方法,只将对象的副本传递给设置对话框。如果用户单击"取消",则不会更新任何内容,但如果用户按"确定",则我希望更改中心设置对象。如果我做

(theLocalSettingsObject) = new Settings(... the values from the dialog); 

中心对象不会得到更新。

我不想手工设置每一个属性,但这是可行的。

正在更新C#中引用的对象

如果您要使用singleton,那么我建议将其设置为静态

public static class Settings
{
    public static string Propery { get; set; }
}

这样你就不需要传递关于的参考

您可以从任何地方访问CCD_ 1。

编辑您的评论

如果你从数据库或其他地方加载设置,请制作一个静态管理器:

public static class SettingsManager
{
    public static Settings Get()
    {
        // get settings from db, memory, wherever
    }
}

您可以使用反射。如果你把代码打包到一个通用的助手类中,你可以像这样调用

PropertyUpdater.Update(mainSettings).With(settingsFromDialog);

其中helper类看起来像这个

public class PropertyUpdater
{
    public static PropertyUpdater<T> Update<T>(T objectToUpdate)
    {
        return PropertyUpdater<T>.Update(objectToUpdate);
    }
}
public class PropertyUpdater<T>
{
    private readonly T destination;
    private PropertyUpdater(T destination)
    {
        this.destination = destination;
    }
    public static PropertyUpdater<T> Update(T objectToUpdate)
    {
        return new PropertyUpdater<T>(objectToUpdate);
    }
    public void With(T objectToCopyFrom)
    {
        PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        foreach (PropertyInfo p in properties)
        {
            // Only copy properties with public get and set methods
            if (!p.CanRead || !p.CanWrite || p.GetGetMethod(false) == null || p.GetSetMethod(false) == null) continue;
            // Skip indexers
            if (p.GetGetMethod(false).GetParameters().Length > 0) continue;
            p.SetValue(this.destination, p.GetValue(objectToCopyFrom, null), null);
        }
    }
}

编辑

因此,从ShellViewModel来看,这将是

private void SaveSettings(Settings settings)
{
    PropertyUpdater.Update(this.Settings).With(settings);
}

这是一个通过的单元测试(MSTest)。

    [TestMethod]
    public void TestMethod1()
    {
        var someClassInstance1 = new ClassA();
        var someClassInstance2 = new ClassA();
        var mainSettings = new Settings
            {
                SomeInt = 1, 
                SomeString = "2", 
                SomeObject = true, 
                SomeClass = someClassInstance1,
                SomeArray = new[] { false }
            };
        var refToMainSettings = mainSettings;
        var dialogSettings = new Settings
            {
                SomeInt = 2,
                SomeString = "3",
                SomeObject = 1.0,
                SomeClass = someClassInstance2,
                SomeArray = new[] { true, false }
            };
        // The magic method :-)
        PropertyUpdater.Update(mainSettings).With(dialogSettings);
        Assert.AreSame(refToMainSettings, mainSettings);
        Assert.AreEqual(2, mainSettings.SomeInt);
        Assert.AreEqual("3", mainSettings.SomeString);
        Assert.IsInstanceOfType(mainSettings.SomeObject, typeof(double));
        Assert.AreEqual(1.0, mainSettings.SomeObject);
        Assert.AreSame(someClassInstance2, mainSettings.SomeClass);
        Assert.AreEqual(2, mainSettings.SomeArray.Length);
        Assert.AreEqual(true, mainSettings.SomeArray[0]);
        Assert.AreEqual(false, mainSettings.SomeArray[1]);
    }
    public class Settings
    {
        public int SomeInt { get; set; }
        public string SomeString { get; set; }
        public object SomeObject { get; set; }
        public ClassA SomeClass { get; set; }
        public bool[] SomeArray { get; set; }
        public bool this[int i]
        {
            get { return SomeArray[i]; }
            set { SomeArray[i] = value; }
        }
    }
    public class ClassA {}

我目前的场景与您相同,我最终创建了一个Copy方法,将所有值从复制设置复制到实际设置。

我实现了一个接一个地调用属性的方法,你,我看不出有任何问题。

realSettings.Copy(tempSettings);

无论如何,我根本不会使用singleton,它们是邪恶的

我同意SoMoS的观点,认为单身汉(就像我经常看到的那样)确实是邪恶的。然而,我建议的另一种选择是利用依赖项注入来确保每个人都有对同一对象的引用。例如,Ninject为它所称的"singleton scope"提供了一个流畅的绑定,它确保每次请求实例时都绑定给定类型的同一对象。我已经广泛使用了这个特殊的模型,它非常有效。您还有一个额外的好处,即"singleton"的消费者不需要知道它是singleton,它们是解耦的,并且可以更容易地进行单元测试。