Пример #1
0
        public void TestOneWayBindingWithConverter()
        {
            int bindingId;
            BindingTestObject    source    = new BindingTestObject();
            BindingTestObject    target    = new BindingTestObject();
            StringToIntConverter converter = new StringToIntConverter();

            bindingId = BindingManager.Register(source, s => s.SourceStringProperty, target,
                                                t => t.SourceIntProperty, default(string), BindingMode.OneWay, converter);

            //After the binding, changes to the source property should be converted to their integer counterparts
            //and propogated to the target
            source.SourceStringProperty = "99";
            Assert.AreEqual(target.SourceIntProperty, 99);

            //However, values that cannot be converted to an integer should cause the fallback value to be used.
            //Since no fallback value was specified, the value should be set to the default of integer type
            source.SourceStringProperty = "Toasty";
            Assert.AreEqual(target.SourceIntProperty, default(int));

            //Also, changes to the target should not affect the source in a OneWay binding
            target.SourceIntProperty = 55;
            Assert.AreNotEqual(source.SourceStringProperty, "55");

            //Disposing of the bindings should cease updates to stop propogating
            BindingManager.Unregister(bindingId);

            source.SourceStringProperty = "-1";
            Assert.AreNotEqual(target.SourceIntProperty, -1);
            Assert.AreEqual(target.SourceIntProperty, 55);
        }
Пример #2
0
        public void TestOneWayBindingNoConverter()
        {
            int bindingId;
            BindingTestObject source = new BindingTestObject();
            BindingTestObject target = new BindingTestObject();

            source.SourceIntProperty = -1;
            target.SourceIntProperty = 200;

            bindingId = BindingManager.Register(source, s => s.SourceIntProperty, target, t => t.SourceIntProperty, default(int), BindingMode.OneWay);

            //After binding, the source and target properties should be in sync
            Assert.AreEqual(source.SourceIntProperty, target.SourceIntProperty);

            //After the binding is created, changes to source should propogate to target
            source.SourceIntProperty = 99;
            Assert.AreEqual(source.SourceIntProperty, target.SourceIntProperty);

            //However, with a OneWay binding, changes to the target should NOT propogate to the source
            target.SourceIntProperty = 66;
            Assert.AreNotEqual(source.SourceIntProperty, target.SourceIntProperty);
            Assert.AreEqual(source.SourceIntProperty, 99);

            //Disposing of a binding should cause updates to stop propogating
            BindingManager.Unregister(bindingId);

            source.SourceIntProperty = 0;
            Assert.AreNotEqual(source.SourceIntProperty, target.SourceIntProperty);
            Assert.AreEqual(target.SourceIntProperty, 66);
        }
Пример #3
0
        public void TestTwoWayBindingNoConversion()
        {
            var bto1 = new BindingTestObject();
            var bto2 = new BindingTestObject();
            int bindingKey;

            Func <object> creator = () =>
            {
                var b1 = new BindingTestObject();
                var b2 = new BindingTestObject();

                BindingManager.Register(b1, b => b.SourceIntProperty, b2, b => b.SourceStringProperty);

                return(null);
            };

            //Should be impossible to create a binding between two properties of different types without a converter
            Assert.ThrowsException <ArgumentException>(creator, "");

            //Can, however, create binding between properties of the same type
            bindingKey = BindingManager.Register(bto1, t => t.SourceIntProperty, bto2, t => t.SourceIntProperty);

            //Binding should cause target to update when source updates
            bto1.SourceIntProperty = 25;
            Assert.AreEqual(bto2.SourceIntProperty, bto1.SourceIntProperty);

            //Binding should also cause source to update when the target updates
            bto2.SourceIntProperty = 99;
            Assert.AreEqual(bto1.SourceIntProperty, bto2.SourceIntProperty);

            //setting unbound properties should cause no changes on target/source objects, as binding occurs
            //on a per-property basis and not for objects as a whole
            bto1.SourceStringProperty = "Toasty";
            bto2.SourceStringProperty = "Not Toasty";

            Assert.AreNotEqual(bto1.SourceStringProperty, bto2.SourceStringProperty);
            Assert.AreEqual(bto1.SourceStringProperty, "Toasty");
            Assert.AreEqual(bto2.SourceStringProperty, "Not Toasty");

            //Disposing of the binding should cease all propogation of updates
            BindingManager.Unregister(bindingKey);

            bto1.SourceIntProperty = -1;
            bto2.SourceIntProperty = 256;

            Assert.AreNotEqual(bto1.SourceIntProperty, bto2.SourceIntProperty);
            Assert.AreEqual(bto1.SourceIntProperty, -1);
            Assert.AreEqual(bto2.SourceIntProperty, 256);
        }
Пример #4
0
        public void TestBindingOptionPerformance()
        {
            MethodInfo getter;
            MethodInfo setter;
            Func <BindingTestObject, int>   getDelegate;
            Action <BindingTestObject, int> setDelegate;
            BindingTestObject bto = new BindingTestObject();
            int  iterations       = 1000;
            long elapsedTicks     = 0;
            int  x;

            //The way I figure it, there are a couple of ways we can handle the process of bindings
            //First, we can use reflection to grab the get/set methods via PropertyInfo.GetxxxMethod() and invoke those on the bound objects
            //Second we can create and cache delegates to the getters and setters
            //Might be other ways, but these are the two that come to mind at the moment

            //First, let's use reflection to grab the getters and setter
            getter      = GetMethodInfo(bto, b => b.SourceIntProperty, "get");
            getDelegate = (Func <BindingTestObject, int>)CreateDelegate(bto, b => b.SourceIntProperty, "get");

            setter      = GetMethodInfo(bto, b => b.SourceIntProperty, "set");
            setDelegate = (Action <BindingTestObject, int>)CreateDelegate(bto, b => b.SourceIntProperty, "set");

            Trace.Write("Testing performance of setting via MethodInfo.Invoke()\n");
            for (int i = 0; i < iterations; i++)
            {
                var timer = Stopwatch.StartNew();
                setter.Invoke(bto, new object[] { i });
                timer.Stop();
                elapsedTicks += timer.ElapsedTicks;
            }

            Trace.Write($"{iterations} iterations of setting via MethodInfo.Invoke took {elapsedTicks} ticks\n");
            Trace.Write("***********************************************************************************\n");
            Trace.Write("Testing performance of setting via cached delegate...\n");
            elapsedTicks = 0;

            //Now test cached delegate setting
            for (int i = 0; i < iterations; i++)
            {
                var timer = Stopwatch.StartNew();
                setDelegate(bto, i);
                timer.Stop();
                elapsedTicks += timer.ElapsedTicks;
            }


            Trace.Write($"{iterations} iterations of setting via cached delegate took {elapsedTicks} ticks\n");
            Trace.Write("***********************************************************************************\n");
            Trace.Write("Testing performance of setting via property get/set methods...\n");
            elapsedTicks = 0;

            //Finally, test the simple property getter
            for (int i = 0; i < iterations; i++)
            {
                var timer = Stopwatch.StartNew();
                bto.SourceIntProperty = i;
                elapsedTicks         += timer.ElapsedTicks;
            }

            Trace.Write($"{iterations} iterations of setting via property get/set took {elapsedTicks} ticks\n");
            Trace.Write("***********************************************************************************\n");
            Trace.Write("Testing performance of getting via MethodInfo.Invoke...\n");
            elapsedTicks = 0;

            //Now test cached MethodInvo.invoke getting
            for (int i = 0; i < iterations; i++)
            {
                var timer = Stopwatch.StartNew();
                getter.Invoke(bto, new object[] { });
                timer.Stop();
                elapsedTicks += timer.ElapsedTicks;
            }

            Trace.Write($"{iterations} iterations of getting via MethodInfo.invoke took {elapsedTicks} ticks\n");
            Trace.Write("***********************************************************************************\n");
            Trace.Write("Testing performance of getting via cached delegate...\n");
            elapsedTicks = 0;

            //Now test cached MethodInvo.invoke getting
            for (int i = 0; i < iterations; i++)
            {
                var timer = Stopwatch.StartNew();
                getDelegate(bto);
                timer.Stop();
                elapsedTicks += timer.ElapsedTicks;
            }

            Trace.Write($"{iterations} iterations of getting via cached delegate took {elapsedTicks} ticks\n");
            Trace.Write("***********************************************************************************\n");
            Trace.Write("Testing performance of getting via property get/set methods...\n");
            elapsedTicks = 0;

            //Finally, test the simple property getter
            for (int i = 0; i < iterations; i++)
            {
                var timer = Stopwatch.StartNew();
                x             = bto.SourceIntProperty;
                elapsedTicks += timer.ElapsedTicks;
            }

            Trace.Write($"{iterations} iterations of getting via property get/set took {elapsedTicks} ticks\n");
            Trace.Write("***********************************************************************************\n");

            //According to the trace output, there is virtually no difference in performance between these two methods for getting and setting (approximately 25 ticks per operation)
            //Interestingly enough, these methods also don't differ from using the property get/set methods themselves,
            //so there should be no noticeable performance degradation from the binding process.
        }