public void QueryPathPriorityPasses()
        {
            var root = new ModelClass()
            {
                Name = "root"
            };
            var apple = new ModelClass()
            {
                Name = "apple"
            };
            var grape = new ModelClass()
            {
                Name = "grape"
            };

            root.AddChildren(apple, grape);
            var orange = new ModelClass()
            {
                Name = "orange", LogicalID = new ModelIDList("child")
            };

            grape.AddChildren(orange);

            var allBinder = new ModelViewBinder("*", null,
                                                new ModelViewBinder.BindInfo(typeof(IntViewObjClass)));
            var appleBinder = new ModelViewBinder("apple", null,
                                                  new ModelViewBinder.BindInfo(typeof(IntViewObjClass)));
            var orangeBinder = new ModelViewBinder("orange", null,
                                                   new ModelViewBinder.BindInfo(typeof(FloatViewObjClass)));
            var childOrangeBinder = new ModelViewBinder("orange #child", null,
                                                        new ModelViewBinder.BindInfo(typeof(FloatViewObjClass)));

            Assert.IsFalse(root.DoMatchQueryPath(appleBinder.Query));

            var viewInstanceCreator = new DefaultViewInstanceCreator(
                (typeof(IntViewObjClass), new IntViewObjClass.Binder()),
                (typeof(FloatViewObjClass), new FloatViewObjClass.Binder())
                );
            var binderMap = new ModelViewBinderMap(
                viewInstanceCreator,
                allBinder,
                appleBinder,
                orangeBinder,
                childOrangeBinder);
            var bindInstanceMap = binderMap.CreateBinderInstaceMap();

            bindInstanceMap.Add(false, null, root.GetHierarchyEnumerable());

            var rootBinderInstance = bindInstanceMap.BindInstances[root];

            Assert.AreSame(allBinder, rootBinderInstance.Binder);

            var appleBinderInstance = bindInstanceMap.BindInstances[apple];

            Assert.AreSame(appleBinder, appleBinderInstance.Binder);

            // grape/orangeのものを使用すること
            var orangeBinderInstance = bindInstanceMap.BindInstances[orange];

            Assert.AreSame(childOrangeBinder, orangeBinderInstance.Binder);

            var grapeBinderInstance = bindInstanceMap.BindInstances[grape];

            Assert.AreSame(allBinder, grapeBinderInstance.Binder);
        }
        public void BasicUsagePasses()
        {
            var root = new ModelClass()
            {
                Name = "root"
            };
            var apple = new ModelClass()
            {
                Name = "apple"
            };
            var grape = new ModelClass()
            {
                Name = "grape"
            };

            root.AddChildren(apple, grape);
            var orange = new ModelClass()
            {
                Name = "orange"
            };

            grape.AddChildren(orange);

            var appleBinder = new ModelViewBinder("apple", null,
                                                  new ModelViewBinder.BindInfo(typeof(IntViewObjClass)));
            var orangeBinder = new ModelViewBinder("orange", null,
                                                   new ModelViewBinder.BindInfo(typeof(FloatViewObjClass)));
            var rebindBinder = new ModelViewBinder("Rebind", null,
                                                   new ModelViewBinder.BindInfo(typeof(FloatViewObjClass)));

            Assert.IsFalse(root.DoMatchQueryPath(appleBinder.Query));
            var viewInstanceCreator = new DefaultViewInstanceCreator(
                (typeof(IntViewObjClass), new IntViewObjClass.Binder()),
                (typeof(FloatViewObjClass), new FloatViewObjClass.Binder())
                );
            var binderMap = new ModelViewBinderMap(viewInstanceCreator, appleBinder, orangeBinder, rebindBinder);
            {//Constructorのテスト
                Assert.AreEqual(3, binderMap.Binders.Count());
                Assert.IsTrue(binderMap.Binders.Any(_b => _b == appleBinder), "指定したBinderがBinderMapの中にありません");
                Assert.IsTrue(binderMap.Binders.Any(_b => _b == orangeBinder), "指定したBinderがBinderMapの中にありません");
                Assert.IsTrue(binderMap.Binders.Any(_b => _b == rebindBinder), "指定したBinderがBinderMapの中にありません");

                Assert.AreSame(viewInstanceCreator, binderMap.ViewInstanceCreator);
                string errorMessage = "ModelViewBinderMapに設定されたModelViewBinder#ViewInstaceCreatorはModelViewBinderMap#ViewInstanceCreatorと同じものになるようにしてください。";
                Assert.AreSame(binderMap.ViewInstanceCreator, appleBinder.ViewInstaceCreator, errorMessage);
                Assert.AreSame(binderMap.ViewInstanceCreator, orangeBinder.ViewInstaceCreator, errorMessage);
                Assert.AreSame(binderMap.ViewInstanceCreator, rebindBinder.ViewInstaceCreator, errorMessage);
            }

            {//ModelViewBindMap#CreateBindInstanceのテスト
                var appleBindInstance  = binderMap.CreateBindInstance(apple, null);
                var orangeBindInstance = binderMap.CreateBindInstance(orange, null);
                Assert.IsNotNull(appleBindInstance);
                Assert.IsNotNull(orangeBindInstance);
                Assert.IsNull(binderMap.CreateBindInstance(root, null));
                Assert.IsNull(binderMap.CreateBindInstance(grape, null));

                Assert.AreSame(apple, appleBindInstance.Model);
                Assert.AreSame(appleBinder, appleBindInstance.Binder);
                Assert.AreEqual(1, appleBindInstance.ViewObjects.Count());
                Assert.AreEqual(typeof(IntViewObjClass), appleBindInstance.ViewObjects.First().GetType());

                Assert.AreSame(orange, orangeBindInstance.Model);
                Assert.AreSame(orangeBinder, orangeBindInstance.Binder);
                Assert.AreEqual(1, orangeBindInstance.ViewObjects.Count());
                Assert.AreEqual(typeof(FloatViewObjClass), orangeBindInstance.ViewObjects.First().GetType());
            }
        }
        public void BinderInstanceMapBasicUsagePasses()
        {
            var root = new ModelClass()
            {
                Name = "root"
            };
            var apple = new ModelClass()
            {
                Name = "apple"
            };
            var noneBinderModel = new ModelClass()
            {
                Name = "grape"
            };

            root.AddChildren(apple, noneBinderModel);
            var orange = new ModelClass()
            {
                Name = "orange"
            };

            noneBinderModel.AddChildren(orange);

            var appleBinder = new ModelViewBinder("apple", null,
                                                  new ModelViewBinder.BindInfo(typeof(IntViewObjClass)));
            var orangeBinder = new ModelViewBinder("orange", null,
                                                   new ModelViewBinder.BindInfo(typeof(FloatViewObjClass)));
            var rebindBinder = new ModelViewBinder("Rebind", null,
                                                   new ModelViewBinder.BindInfo(typeof(FloatViewObjClass)));

            Assert.IsFalse(root.DoMatchQueryPath(appleBinder.Query));
            var viewInstanceCreator = new DefaultViewInstanceCreator(
                (typeof(IntViewObjClass), new IntViewObjClass.Binder()),
                (typeof(FloatViewObjClass), new FloatViewObjClass.Binder())
                );
            var binderMap = new ModelViewBinderMap(viewInstanceCreator, appleBinder, orangeBinder, rebindBinder);

            {//BinderInstanceMapのテスト
                var bindInstanceMap = new ModelViewBinderInstanceMap(binderMap);
                Assert.AreSame(binderMap, bindInstanceMap.BinderMap);

                {//BindInstanceMap#Addのテスト
                    Assert.AreEqual(0, bindInstanceMap.BindInstances.Count());
                    bindInstanceMap.Add(false, null, apple, noneBinderModel);
                    //grapeはQueryPathと一致しないので追加されない
                    AssertionUtils.AssertEnumerableByUnordered(new Model[] {
                        apple, orange
                    }, bindInstanceMap.BindInstances.Select(_b => _b.Key), "");

                    //追加された時は合わせてViewのパラメータもModelのものに更新する
                    var appleViewObj = bindInstanceMap[apple].ViewObjects.First(_v => _v is IntViewObjClass) as IntViewObjClass;
                    Assert.AreEqual(apple.IntValue, appleViewObj.IntValue);
                    foreach (var viewObj in bindInstanceMap[apple].ViewObjects)
                    {
                        Assert.AreEqual(bindInstanceMap[apple], viewObj.UseBinderInstance);
                    }
                    Assert.AreSame(bindInstanceMap, bindInstanceMap[apple].UseInstanceMap);

                    var orangeViewObj = bindInstanceMap[orange].ViewObjects.First(_v => _v is FloatViewObjClass) as FloatViewObjClass;
                    Assert.AreEqual(orange.FloatValue, orangeViewObj.FloatValue);
                    foreach (var viewObj in bindInstanceMap[orange].ViewObjects)
                    {
                        Assert.AreEqual(bindInstanceMap[orange], viewObj.UseBinderInstance);
                    }

                    //既に追加されていたら追加しない
                    bindInstanceMap.Add(false, null, apple, orange);
                    AssertionUtils.AssertEnumerableByUnordered(new Model[] {
                        apple, orange
                    }, bindInstanceMap.BindInstances.Select(_b => _b.Key), "同じModelが追加できないようにしてください");
                }

                {//マッチしないModelを追加した時のテスト
                    var empty = new Model()
                    {
                        Name = "__empty"
                    };
                    Assert.DoesNotThrow(() =>
                    {
                        bindInstanceMap.Add(empty);
                        Assert.IsFalse(bindInstanceMap.BindInstances.ContainsKey(empty), "マッチしないModelを追加した時はModelViewBinderInstanceを生成しないようにしてください");
                    }, "マッチしないModelを追加した時でもModelViewBinderInstanceMapから例外を発生させないようにしてください。");
                }

                var appleBindInstance  = bindInstanceMap[apple];
                var orangeBindInstance = bindInstanceMap[orange];
                {//BindInstanceMap#[]のテスト
                    Assert.IsNotNull(appleBindInstance);
                    Assert.AreEqual(apple, appleBindInstance.Model);

                    Assert.IsNotNull(orangeBindInstance);
                    Assert.AreEqual(orange, orangeBindInstance.Model);
                }

                {//BindInstanceMap#UpdateViewObjectsのテスト
                    apple.IntValue    = 234;
                    orange.FloatValue = 2.5432f;
                    bindInstanceMap.UpdateViewObjects();
                    var appleViewObj = appleBindInstance.ViewObjects.First(_v => _v is IntViewObjClass) as IntViewObjClass;
                    Assert.AreEqual(apple.IntValue, appleViewObj.IntValue);
                    var orangeViewObj = orangeBindInstance.ViewObjects.First(_v => _v is FloatViewObjClass) as FloatViewObjClass;
                    Assert.AreEqual(orange.FloatValue, orangeViewObj.FloatValue);
                }

                {//BindInstanceMap#Rebindのテスト
                    apple.Name = "Rebind";
                    var isSuccess = bindInstanceMap.Rebind(apple);
                    Assert.IsTrue(isSuccess, "Rebindに失敗しています");
                    Assert.AreSame(rebindBinder, bindInstanceMap.BindInstances[apple].Binder);
                    Assert.AreSame(bindInstanceMap, bindInstanceMap.BindInstances[apple].UseInstanceMap);
                }
                {
                    // 追加されていないものをRebindした時は何もしない
                    var recordedBindInstances = bindInstanceMap.BindInstances.ToArray();
                    var model = new ModelClass()
                    {
                        Name = "Tmp"
                    };
                    var isSuccess = bindInstanceMap.Rebind(model);
                    Assert.IsFalse(isSuccess, "登録されていないModelの場合はRebindしないようにしてください");
                    AssertionUtils.AssertEnumerable(recordedBindInstances, bindInstanceMap.BindInstances, "ModelViewBinderInstanceMapに追加されていないModelをRebindした時は何もしないようにしてください。");
                }

                {//BindInstanceMap#Removeのテスト
                    bindInstanceMap.Remove(apple, noneBinderModel);
                    Assert.AreEqual(0, bindInstanceMap.BindInstances.Count());
                }

                {//BindInstanceMap#ClearBindInstancesのテスト
                    bindInstanceMap.Add(false, null, apple, orange);
                    bindInstanceMap.ClearBindInstances();
                    Assert.AreEqual(0, bindInstanceMap.BindInstances.Count());
                }
            }
        }