在C#中更新引用的对象

时间:2012-03-02 14:48:10

标签: c# .net-4.0

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

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

中心对象不会更新。

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

4 个答案:

答案 0 :(得分:2)

如果你要使用单身人士,那么我建议将其设为静态

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

这样你就不需要传递关于

的引用了

您可以随时随地访问Settings.Property

编辑您的评论

如果您从数据库或其他东西加载设置,请改为使用静态管理器:

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

答案 1 :(得分:0)

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

我实现了逐个调用属性的方法,我没有看到任何问题。

realSettings.Copy(tempSettings);

无论如何我根本不会使用单身人士,他们是evil

答案 2 :(得分:0)

我同意SoMoS的观点,那就是单身人士(就像我经常看到的那样)确实是evil。但是,我建议的另一种方法是利用依赖注入来确保每个人都有对同一对象的引用。例如,Ninject对它所谓的“singleton scope”具有流畅的绑定,它确保每次请求实例时绑定给定类型的相同对象。我已经广泛使用了这个特殊的模型并且效果很好。您还有一个额外的好处,即“单身人士”的消费者不需要知道它是单身,它们是分离的,并且可以更容易地进行单元测试。

答案 3 :(得分:0)

您可以使用反射。如果将代码打包到通用帮助程序类中,则可以像这样调用

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

辅助类看起来像这样

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 {}