1

クラスのオプションとして配列を渡し、そのPHP配列をデフォルトを保持する別の配列セットとマージするのが一般的な方法です。

このようなもの。

class MyObject
{
     private static $defaults = array('value'=>10);
     private $settings;

     public function Something(array $settings = array())
     {
          $this->settings = array_merge(static::defaults,$settings);
     }
}

jQueryまたは関数を導入する他のライブラリを使用して、JavaScriptで何かを行うことができますmerge。これらのスクリプトを使用すると、2 つの Javascript オブジェクトを取得して、それらをマージできます。1 つをデフォルトとして使用し、別のデフォルトを上書きすることができます。

このパターンは、必要な設定のみを割り当てながら、多数のデフォルト セットを構成できるため、非常に便利です。

とにかくこのようなことをすることはありますC#か?

リフレクションを使用してパブリック プロパティでこれを行う関数を作成することはできますが、このようなことは既に行われているに違いないと考えていました。

編集:

この質問は以前にスタックで尋ねられましたが、PHP や Javascript でできることと同じように簡単に答えられませんでした。

4

1 に答える 1

0

私が望んでいたことを正確に行う答えを見つけることができませんでした。だから私はこれを行うための小さな方法を書きました。同時に 2 つのオブジェクトを取得し、null値が割り当てられていないフィールド/プロパティを表すと仮定して、それらのフィールド/プロパティをマージします。

使用例はこちら。通信クラスのオプションを保持するクラスを作成し、通信クラスにデフォルトを設定してから、ユーザー設定で通信を初期化します。

設定クラスの例。

public class ComSettings
{
    public int? Port;
    public string? Address;
    public bool? KeepAlive;
}

コンストラクターでこれらの設定を使用するクラスの例。

public class ComLibrary
{
    private static ComSettings _defaults = new ComSettings { Port = 80, Address = "localhost" };

    protected ComSettings settings;

    public ComLibrary(ComSettings pSettings)
    {
        this.settings = ObjectMerge<ComSettings>(_defaults, pSettings);
    }
}

これにより、異なるクラスが を使用できるようにComSettingsなりますが、それぞれが異なるデフォルトを持つ可能性があります。唯一の制限は、フィールド/プロパティがnull割り当てをサポートする必要があることです。

の実装はこちらObjectMerge

    /// <summary>
    /// Creates a new object that contains the properties of the two objects merged together.
    /// </summary>
    /// <typeparam name="T">The class type to merge.</typeparam>
    /// <param name="pDefaults">Instance of the defaults object.</param>
    /// <param name="pSettings">Instance of the settings object.</param>
    /// <returns>A new instance of T with the merged results.</returns>
    public static T ObjectMerge<T>(T pDefaults, T pSettings, bool pMergeFields = true, bool pMergeProperties = true) where T : class, new()
    {
        T target = new T();
        Type type = typeof(T);
        List<MemberInfo> infos = new List<MemberInfo>(type.GetMembers());

        foreach (MemberInfo info in infos)
        {
            // Copy values from either defaults or settings
            if (pMergeFields && info.MemberType == MemberTypes.Field)
            {
                FieldInfo field = (FieldInfo)info;
                if (field.IsPublic)
                {
                    object value = field.GetValue(pSettings);
                    value = (value == null) ? field.GetValue(pDefaults) : value;
                    field.SetValue(target, value);
                }
            }

            // Copy values from either defaults or settings
            if (pMergeProperties && info.MemberType == MemberTypes.Property)
            {
                PropertyInfo prop = (PropertyInfo)info;
                if (prop.CanWrite && prop.CanRead)
                {
                    object value = prop.GetValue(pSettings, null);
                    value = (value == null) ? prop.GetValue(pDefaults, null) : value;
                    prop.SetValue(target, value, null);
                }
            }
        }

        return target;
    }

そして、ここに簡単な単体テストがあります。

/// <summary>
///This is a test class for CoreUtilsTest and is intended
///to contain all CoreUtilsTest Unit Tests
///</summary>
[TestClass()]
public class CoreUtilsTest
{
    /// <summary>
    /// A class to perform testing on.
    /// </summary>
    public class MyClassA
    {
        public string Param1;
        public string Param2;
        public string Param3;
    }

    /// <summary>
    /// A class to perform testing on.
    /// </summary>
    public class MyClassB
    {
        private string _param1;

        public string Param1
        {
            get { return _param1; }
            set { _param1 = value; }
        }
        private string _param2;

        public string Param2
        {
            get { return _param2; }
            set { _param2 = value; }
        }
        private string _param3;

        public string Param3
        {
            get { return _param3; }
            set { _param3 = value; }
        }
    }

    /// <summary>
    ///A test for SetProperties
    ///</summary>
    [TestMethod()]
    public void Merging_Fields()
    {
        MyClassA defaults = new MyClassA { Param1 = "defaults" };
        MyClassA settings = new MyClassA { Param2 = "settings" };
        MyClassA results = CoreUtils.ObjectMerge<MyClassA>(defaults, settings);

        Assert.AreEqual("defaults", results.Param1);
        Assert.AreEqual("settings", results.Param2);
        Assert.AreEqual(null, results.Param3);
    }

    [TestMethod()]
    public void Merging_Properties()
    {
        MyClassB defaults = new MyClassB { Param1 = "defaults" };
        MyClassB settings = new MyClassB { Param2 = "settings" };
        MyClassB results = CoreUtils.ObjectMerge<MyClassB>(defaults, settings);

        Assert.AreEqual("defaults", results.Param1);
        Assert.AreEqual("settings", results.Param2);
        Assert.AreEqual(null, results.Param3);
    }

}
于 2013-05-19T21:17:00.383 に答える