ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sboi...@apache.org
Subject [4/5] ignite git commit: IGNITE-2380: Added ability to start Ignite using configuration from app.config. This closes #417.
Date Tue, 09 Feb 2016 16:11:04 GMT
IGNITE-2380: Added ability to start Ignite using configuration from app.config. This closes #417.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a4d8a049
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a4d8a049
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a4d8a049

Branch: refs/heads/ignite-2587
Commit: a4d8a049138a4d4bc86a59ccb273f7e214baf694
Parents: f7c1296
Author: Pavel Tupitsyn <ptupitsyn@gridgain.com>
Authored: Tue Feb 9 14:54:20 2016 +0300
Committer: vozerov-gridgain <vozerov@gridgain.com>
Committed: Tue Feb 9 14:54:20 2016 +0300

----------------------------------------------------------------------
 .../Apache.Ignite.Core.Tests.csproj             |   4 +
 .../Apache.Ignite.Core.Tests/FutureTest.cs      |   1 +
 .../IgniteConfigurationSectionTest.cs           |  69 +++
 .../IgniteConfigurationSerializerTest.cs        | 554 +++++++++++++++++++
 .../dotnet/Apache.Ignite.Core.Tests/app.config  |  54 ++
 .../Apache.Ignite.Core.csproj                   |  11 +
 .../Binary/IBinarySerializer.cs                 |   6 +-
 .../IgniteConfigurationSection.cs               |  80 +++
 .../IgniteConfigurationSection.xsd              | 281 ++++++++++
 .../dotnet/Apache.Ignite.Core/Ignition.cs       |  39 ++
 .../Impl/Common/BooleanLowerCaseConverter.cs    |  60 ++
 .../Common/IgniteConfigurationXmlSerializer.cs  | 410 ++++++++++++++
 .../Impl/Common/TypeStringConverter.cs          | 115 ++++
 .../Impl/Events/EventTypeConverter.cs           | 133 +++++
 14 files changed, 1814 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index f5e98c5..fb14ed5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -55,6 +55,7 @@
       <HintPath>..\libs\nunit.framework.dll</HintPath>
     </Reference>
     <Reference Include="System" />
+    <Reference Include="System.configuration" />
     <Reference Include="System.Core" />
     <Reference Include="System.Runtime.Serialization" />
     <Reference Include="System.XML" />
@@ -117,6 +118,8 @@
     <Compile Include="ExceptionsTest.cs" />
     <Compile Include="ExecutableTest.cs" />
     <Compile Include="FutureTest.cs" />
+    <Compile Include="IgniteConfigurationSectionTest.cs" />
+    <Compile Include="IgniteConfigurationSerializerTest.cs" />
     <Compile Include="IgniteConfigurationTest.cs" />
     <Compile Include="IgniteTestBase.cs" />
     <Compile Include="LifecycleTest.cs" />
@@ -251,6 +254,7 @@
   <ItemGroup>
     <None Include="Apache.Ignite.Core.Tests.nunit" />
     <None Include="Apache.Ignite.Core.Tests.snk" />
+    <None Include="app.config" />
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>

http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core.Tests/FutureTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/FutureTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/FutureTest.cs
index f18be8c..bc1f08f 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/FutureTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/FutureTest.cs
@@ -67,6 +67,7 @@ namespace Apache.Ignite.Core.Tests
         [TestFixtureTearDown]
         public void TestFixtureTearDown()
         {
+            Ignition.StopAll(true);
             TestUtils.KillProcesses();
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSectionTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSectionTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSectionTest.cs
new file mode 100644
index 0000000..29aea90
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSectionTest.cs
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Tests
+{
+    using System;
+    using System.Configuration;
+    using System.Linq;
+    using Apache.Ignite.Core.Impl.Common;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests <see cref="IgniteConfigurationSection"/>.
+    /// </summary>
+    public class IgniteConfigurationSectionTest
+    {
+        /// <summary>
+        /// Tests the read.
+        /// </summary>
+        [Test]
+        public void TestRead()
+        {
+            var section = (IgniteConfigurationSection) ConfigurationManager.GetSection("igniteConfiguration");
+
+            Assert.AreEqual("myGrid1", section.IgniteConfiguration.GridName);
+            Assert.AreEqual("cacheName", section.IgniteConfiguration.CacheConfiguration.Single().Name);
+        }
+
+        /// <summary>
+        /// Tests the ignite start.
+        /// </summary>
+        [Test]
+        public void TestIgniteStart()
+        {
+            Environment.SetEnvironmentVariable(Classpath.EnvIgniteNativeTestClasspath, "true");
+
+            using (var ignite = Ignition.StartFromApplicationConfiguration("igniteConfiguration"))
+            {
+                Assert.AreEqual("myGrid1", ignite.Name);
+                Assert.IsNotNull(ignite.GetCache<int, int>("cacheName"));
+            }
+
+            using (var ignite = Ignition.StartFromApplicationConfiguration("igniteConfiguration2"))
+            {
+                Assert.AreEqual("myGrid2", ignite.Name);
+                Assert.IsNotNull(ignite.GetCache<int, int>("cacheName2"));
+            }
+
+            using (var ignite = Ignition.StartFromApplicationConfiguration())
+            {
+                Assert.IsTrue(ignite.Name.StartsWith("myGrid"));
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
new file mode 100644
index 0000000..d8c52ee
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
@@ -0,0 +1,554 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable MemberCanBePrivate.Global
+namespace Apache.Ignite.Core.Tests
+{
+    using System;
+    using System.Collections;
+    using System.Collections.Generic;
+    using System.Globalization;
+    using System.IO;
+    using System.Linq;
+    using System.Text;
+    using System.Threading;
+    using System.Xml;
+    using System.Xml.Schema;
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Cache.Configuration;
+    using Apache.Ignite.Core.Cache.Store;
+    using Apache.Ignite.Core.Common;
+    using Apache.Ignite.Core.Discovery.Tcp;
+    using Apache.Ignite.Core.Discovery.Tcp.Multicast;
+    using Apache.Ignite.Core.Events;
+    using Apache.Ignite.Core.Impl.Common;
+    using Apache.Ignite.Core.Lifecycle;
+    using Apache.Ignite.Core.Tests.Binary;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests <see cref="IgniteConfiguration"/> serialization.
+    /// </summary>
+    public class IgniteConfigurationSerializerTest
+    {
+        /// <summary>
+        /// Tests the predefined XML.
+        /// </summary>
+        [Test]
+        public void TestPredefinedXml()
+        {
+            var xml = @"<igniteConfig workDirectory='c:' JvmMaxMemoryMb='1024' MetricsLogFrequency='0:0:10'>
+                            <localhost>127.1.1.1</localhost>
+                            <binaryConfiguration>
+                                <defaultNameMapper type='Apache.Ignite.Core.Tests.IgniteConfigurationSerializerTest+NameMapper, Apache.Ignite.Core.Tests' bar='testBar' />
+                                <types>
+                                    <string>Apache.Ignite.Core.Tests.IgniteConfigurationSerializerTest+FooClass, Apache.Ignite.Core.Tests</string>
+                                </types>
+                            </binaryConfiguration>
+                            <discoverySpi type='TcpDiscoverySpi' joinTimeout='0:1:0'>
+                                <ipFinder type='TcpDiscoveryMulticastIpFinder' addressRequestAttempts='7' />
+                            </discoverySpi>
+                            <jvmOptions><string>-Xms1g</string><string>-Xmx4g</string></jvmOptions>
+                            <lifecycleBeans>
+                                <iLifecycleBean type='Apache.Ignite.Core.Tests.IgniteConfigurationSerializerTest+LifecycleBean, Apache.Ignite.Core.Tests' foo='15' />
+                            </lifecycleBeans>
+                            <cacheConfiguration>
+                                <cacheConfiguration cacheMode='Replicated'>
+                                    <queryEntities>    
+                                        <queryEntity keyType='System.Int32' valueType='System.String'>    
+                                            <fields>
+                                                <queryField name='length' fieldType='System.Int32' />
+                                            </fields>
+                                            <aliases>
+                                                <queryAlias fullName='somefield.field' alias='shortField' />
+                                            </aliases>
+                                            <indexes>
+                                                <queryIndex name='idx' indexType='Geospatial'>
+                                                    <fields>
+                                                        <queryIndexField name='indexFld' isDescending='true' />
+                                                    </fields>
+                                                </queryIndex>
+                                            </indexes>
+                                        </queryEntity>
+                                    </queryEntities>
+                                </cacheConfiguration>
+                                <cacheConfiguration name='secondCache' />
+                            </cacheConfiguration>
+                            <includedEventTypes>
+                                <int>42</int>
+                                <int>TaskFailed</int>
+                                <int>JobFinished</int>
+                            </includedEventTypes>
+                        </igniteConfig>";
+            var reader = XmlReader.Create(new StringReader(xml));
+
+            var cfg = IgniteConfigurationXmlSerializer.Deserialize(reader);
+
+            Assert.AreEqual("c:", cfg.WorkDirectory);
+            Assert.AreEqual("127.1.1.1", cfg.Localhost);
+            Assert.AreEqual(1024, cfg.JvmMaxMemoryMb);
+            Assert.AreEqual(TimeSpan.FromSeconds(10), cfg.MetricsLogFrequency);
+            Assert.AreEqual(TimeSpan.FromMinutes(1), ((TcpDiscoverySpi)cfg.DiscoverySpi).JoinTimeout);
+            Assert.AreEqual(7,
+                ((TcpDiscoveryMulticastIpFinder) ((TcpDiscoverySpi) cfg.DiscoverySpi).IpFinder).AddressRequestAttempts);
+            Assert.AreEqual(new[] { "-Xms1g", "-Xmx4g" }, cfg.JvmOptions);
+            Assert.AreEqual(15, ((LifecycleBean) cfg.LifecycleBeans.Single()).Foo);
+            Assert.AreEqual("testBar", ((NameMapper) cfg.BinaryConfiguration.DefaultNameMapper).Bar);
+            Assert.AreEqual(
+                "Apache.Ignite.Core.Tests.IgniteConfigurationSerializerTest+FooClass, Apache.Ignite.Core.Tests",
+                cfg.BinaryConfiguration.Types.Single());
+            Assert.AreEqual(new[] {42, EventType.TaskFailed, EventType.JobFinished}, cfg.IncludedEventTypes);
+
+            Assert.AreEqual("secondCache", cfg.CacheConfiguration.Last().Name);
+
+            var cacheCfg = cfg.CacheConfiguration.First();
+
+            Assert.AreEqual(CacheMode.Replicated, cacheCfg.CacheMode);
+
+            var queryEntity = cacheCfg.QueryEntities.Single();
+            Assert.AreEqual(typeof(int), queryEntity.KeyType);
+            Assert.AreEqual(typeof(string), queryEntity.ValueType);
+            Assert.AreEqual("length", queryEntity.Fields.Single().Name);
+            Assert.AreEqual(typeof(int), queryEntity.Fields.Single().FieldType);
+            Assert.AreEqual("somefield.field", queryEntity.Aliases.Single().FullName);
+            Assert.AreEqual("shortField", queryEntity.Aliases.Single().Alias);
+            Assert.AreEqual(QueryIndexType.Geospatial, queryEntity.Indexes.Single().IndexType);
+            Assert.AreEqual("indexFld", queryEntity.Indexes.Single().Fields.Single().Name);
+            Assert.AreEqual(true, queryEntity.Indexes.Single().Fields.Single().IsDescending);
+        }
+
+        /// <summary>
+        /// Tests the serialize deserialize.
+        /// </summary>
+        [Test]
+        public void TestSerializeDeserialize()
+        {
+            // Test custom
+            CheckSerializeDeserialize(GetTestConfig());
+
+            // Test custom with different culture to make sure numbers are serialized properly
+            RunWithCustomCulture(() => CheckSerializeDeserialize(GetTestConfig()));
+            
+            // Test default
+            CheckSerializeDeserialize(new IgniteConfiguration());
+        }
+
+        /// <summary>
+        /// Tests the schema validation.
+        /// </summary>
+        [Test]
+        public void TestSchemaValidation()
+        {
+            CheckSchemaValidation();
+
+            RunWithCustomCulture(CheckSchemaValidation);
+
+            // Check invalid xml
+            const string invalidXml =
+                @"<igniteConfiguration xmlns='http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection'>
+                    <binaryConfiguration /><binaryConfiguration />
+                  </igniteConfiguration>";
+
+            Assert.Throws<XmlSchemaValidationException>(() => CheckSchemaValidation(invalidXml));
+        }
+
+        /// <summary>
+        /// Checks the schema validation.
+        /// </summary>
+        private static void CheckSchemaValidation()
+        {
+            var sb = new StringBuilder();
+
+            using (var xmlWriter = XmlWriter.Create(sb))
+            {
+                IgniteConfigurationXmlSerializer.Serialize(GetTestConfig(), xmlWriter, "igniteConfiguration");
+            }
+
+            CheckSchemaValidation(sb.ToString());
+        }
+
+        /// <summary>
+        /// Checks the schema validation.
+        /// </summary>
+        /// <param name="xml">The XML.</param>
+        private static void CheckSchemaValidation(string xml)
+        {
+            var document = new XmlDocument();
+
+            document.Schemas.Add("http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection", 
+                XmlReader.Create("IgniteConfigurationSection.xsd"));
+
+            document.Load(new StringReader(xml));
+
+            document.Validate(null);
+        }
+
+        /// <summary>
+        /// Checks the serialize deserialize.
+        /// </summary>
+        /// <param name="cfg">The config.</param>
+        private static void CheckSerializeDeserialize(IgniteConfiguration cfg)
+        {
+            var resCfg = SerializeDeserialize(cfg);
+
+            AssertReflectionEqual(cfg, resCfg);
+        }
+
+        /// <summary>
+        /// Serializes and deserializes a config.
+        /// </summary>
+        private static IgniteConfiguration SerializeDeserialize(IgniteConfiguration cfg)
+        {
+            var sb = new StringBuilder();
+
+            using (var xmlWriter = XmlWriter.Create(sb))
+            {
+                IgniteConfigurationXmlSerializer.Serialize(cfg, xmlWriter, "igniteConfig");
+            }
+
+            var xml = sb.ToString();
+
+            using (var xmlReader = XmlReader.Create(new StringReader(xml)))
+            {
+                xmlReader.MoveToContent();
+                return IgniteConfigurationXmlSerializer.Deserialize(xmlReader);
+            }
+        }
+
+        /// <summary>
+        /// Asserts equality with reflection.
+        /// </summary>
+        private static void AssertReflectionEqual(object x, object y)
+        {
+            var type = x.GetType();
+
+            Assert.AreEqual(type, y.GetType());
+
+            if (type.IsValueType || type == typeof (string) || type.IsSubclassOf(typeof (Type)))
+            {
+                Assert.AreEqual(x, y);
+                return;
+            }
+
+            var props = type.GetProperties();
+
+            foreach (var propInfo in props)
+            {
+                var propType = propInfo.PropertyType;
+
+                var xVal = propInfo.GetValue(x, null);
+                var yVal = propInfo.GetValue(y, null);
+
+                if (xVal == null || yVal == null)
+                {
+                    Assert.IsNull(xVal);
+                    Assert.IsNull(yVal);
+                }
+                else if (propType != typeof(string) && propType.IsGenericType 
+                    && propType.GetGenericTypeDefinition() == typeof (ICollection<>))
+                {
+                    var xCol = ((IEnumerable) xVal).OfType<object>().ToList();
+                    var yCol = ((IEnumerable) yVal).OfType<object>().ToList();
+
+                    Assert.AreEqual(xCol.Count, yCol.Count);
+
+                    for (int i = 0; i < xCol.Count; i++)
+                        AssertReflectionEqual(xCol[i], yCol[i]);
+                }
+                else
+                {
+                    AssertReflectionEqual(xVal, yVal);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the test configuration.
+        /// </summary>
+        private static IgniteConfiguration GetTestConfig()
+        {
+            return new IgniteConfiguration
+            {
+                GridName = "gridName",
+                JvmOptions = new[] {"1", "2"},
+                Localhost = "localhost11",
+                JvmClasspath = "classpath",
+                Assemblies = new[] {"asm1", "asm2", "asm3"},
+                BinaryConfiguration = new BinaryConfiguration
+                {
+                    TypeConfigurations = new[]
+                    {
+                        new BinaryTypeConfiguration
+                        {
+                            IsEnum = true,
+                            KeepDeserialized = true,
+                            AffinityKeyFieldName = "affKeyFieldName",
+                            TypeName = "typeName",
+                            IdMapper = new IdMapper(),
+                            NameMapper = new NameMapper(),
+                            Serializer = new TestSerializer()
+                        }
+                    },
+                    DefaultIdMapper = new IdMapper(),
+                    DefaultKeepDeserialized = true,
+                    DefaultNameMapper = new NameMapper(),
+                    DefaultSerializer = new TestSerializer()
+                },
+                CacheConfiguration = new[]
+                {
+                    new CacheConfiguration("cacheName")
+                    {
+                        AtomicWriteOrderMode = CacheAtomicWriteOrderMode.Primary,
+                        AtomicityMode = CacheAtomicityMode.Transactional,
+                        Backups = 15,
+                        CacheMode = CacheMode.Partitioned,
+                        CacheStoreFactory = new TestCacheStoreFactory(),
+                        CopyOnRead = true,
+                        EagerTtl = true,
+                        EnableSwap = true,
+                        EvictSynchronized = true,
+                        EvictSynchronizedConcurrencyLevel = 13,
+                        EvictSynchronizedKeyBufferSize = 14,
+                        EvictSynchronizedTimeout = TimeSpan.FromMinutes(3),
+                        Invalidate = true,
+                        KeepBinaryInStore = true,
+                        LoadPreviousValue = true,
+                        LockTimeout = TimeSpan.FromSeconds(56),
+                        LongQueryWarningTimeout = TimeSpan.FromSeconds(99),
+                        MaxConcurrentAsyncOperations = 24,
+                        MaxEvictionOverflowRatio = 5.6F,
+                        MemoryMode = CacheMemoryMode.OffheapValues,
+                        OffHeapMaxMemory = 567,
+                        QueryEntities = new[]
+                        {
+                            new QueryEntity
+                            {
+                                Fields = new[]
+                                {
+                                    new QueryField("field", typeof (int))
+                                },
+                                Indexes = new[]
+                                {
+                                    new QueryIndex("field") { IndexType = QueryIndexType.FullText }
+                                },
+                                Aliases = new[]
+                                {
+                                    new QueryAlias("field.field", "fld")
+                                },
+                                KeyType = typeof (string),
+                                ValueType = typeof (long)
+                            },
+                        },
+                        ReadFromBackup = true,
+                        RebalanceBatchSize = 33,
+                        RebalanceDelay = TimeSpan.MaxValue,
+                        RebalanceMode = CacheRebalanceMode.Sync,
+                        RebalanceThrottle = TimeSpan.FromHours(44),
+                        RebalanceTimeout = TimeSpan.FromMinutes(8),
+                        SqlEscapeAll = true,
+                        SqlOnheapRowCacheSize = 679,
+                        StartSize = 1023,
+                        WriteBehindBatchSize = 45,
+                        WriteBehindEnabled = true,
+                        WriteBehindFlushFrequency = TimeSpan.FromSeconds(5),
+                        WriteBehindFlushSize = 66,
+                        WriteBehindFlushThreadCount = 2,
+                        WriteSynchronizationMode = CacheWriteSynchronizationMode.FullAsync
+                    }
+                },
+                ClientMode = true,
+                DiscoverySpi = new TcpDiscoverySpi
+                {
+                    NetworkTimeout = TimeSpan.FromSeconds(1),
+                    SocketTimeout = TimeSpan.FromSeconds(2),
+                    AckTimeout = TimeSpan.FromSeconds(3),
+                    JoinTimeout = TimeSpan.FromSeconds(4),
+                    MaxAckTimeout = TimeSpan.FromSeconds(5),
+                    IpFinder = new TcpDiscoveryMulticastIpFinder
+                    {
+                        TimeToLive = 110,
+                        MulticastGroup = "multicastGroup",
+                        AddressRequestAttempts = 10,
+                        MulticastPort = 987,
+                        ResponseTimeout = TimeSpan.FromDays(1),
+                        LocalAddress = "127.0.0.2",
+                        Endpoints = new[] {"", "abc"}
+                    }
+                },
+                IgniteHome = "igniteHome",
+                IncludedEventTypes = EventType.CacheQueryAll,
+                JvmDllPath = @"c:\jvm",
+                JvmInitialMemoryMb = 1024,
+                JvmMaxMemoryMb = 2048,
+                LifecycleBeans = new[] {new LifecycleBean(), new LifecycleBean() },
+                MetricsExpireTime = TimeSpan.FromSeconds(15),
+                MetricsHistorySize = 45,
+                MetricsLogFrequency = TimeSpan.FromDays(2),
+                MetricsUpdateFrequency = TimeSpan.MinValue,
+                NetworkSendRetryCount = 7,
+                NetworkSendRetryDelay = TimeSpan.FromSeconds(98),
+                NetworkTimeout = TimeSpan.FromMinutes(4),
+                SuppressWarnings = true,
+                WorkDirectory = @"c:\work"
+            };
+        }
+
+        /// <summary>
+        /// Runs the with custom culture.
+        /// </summary>
+        /// <param name="action">The action.</param>
+        private static void RunWithCustomCulture(Action action)
+        {
+            RunWithCulture(action, CultureInfo.InvariantCulture);
+            RunWithCulture(action, CultureInfo.GetCultureInfo("ru-RU"));
+        }
+
+        /// <summary>
+        /// Runs the with culture.
+        /// </summary>
+        /// <param name="action">The action.</param>
+        /// <param name="cultureInfo">The culture information.</param>
+        private static void RunWithCulture(Action action, CultureInfo cultureInfo)
+        {
+            var oldCulture = Thread.CurrentThread.CurrentCulture;
+
+            try
+            {
+                Thread.CurrentThread.CurrentCulture = cultureInfo;
+
+                action();
+            }
+            finally
+            {
+                Thread.CurrentThread.CurrentCulture = oldCulture;
+            }
+        }
+
+        /// <summary>
+        /// Test bean.
+        /// </summary>
+        public class LifecycleBean : ILifecycleBean
+        {
+            /// <summary>
+            /// Gets or sets the foo.
+            /// </summary>
+            /// <value>
+            /// The foo.
+            /// </value>
+            public int Foo { get; set; }
+
+            /// <summary>
+            /// This method is called when lifecycle event occurs.
+            /// </summary>
+            /// <param name="evt">Lifecycle event.</param>
+            public void OnLifecycleEvent(LifecycleEventType evt)
+            {
+                // No-op.
+            }
+        }
+
+        /// <summary>
+        /// Test mapper.
+        /// </summary>
+        public class NameMapper : IBinaryNameMapper
+        {
+            /// <summary>
+            /// Gets or sets the bar.
+            /// </summary>
+            /// <value>
+            /// The bar.
+            /// </value>
+            public string Bar { get; set; }
+
+            /// <summary>
+            /// Gets the type name.
+            /// </summary>
+            /// <param name="name">The name.</param>
+            /// <returns>
+            /// Type name.
+            /// </returns>
+            public string GetTypeName(string name)
+            {
+                return name;
+            }
+
+            /// <summary>
+            /// Gets the field name.
+            /// </summary>
+            /// <param name="name">The name.</param>
+            /// <returns>
+            /// Field name.
+            /// </returns>
+            public string GetFieldName(string name)
+            {
+                return name;
+            }
+        }
+
+        /// <summary>
+        /// Serializer.
+        /// </summary>
+        public class TestSerializer : IBinarySerializer
+        {
+            /// <summary>
+            /// Write portalbe object.
+            /// </summary>
+            /// <param name="obj">Object.</param>
+            /// <param name="writer">Poratble writer.</param>
+            public void WriteBinary(object obj, IBinaryWriter writer)
+            {
+                // No-op.
+            }
+
+            /// <summary>
+            /// Read binary object.
+            /// </summary>
+            /// <param name="obj">Instantiated empty object.</param>
+            /// <param name="reader">Poratble reader.</param>
+            public void ReadBinary(object obj, IBinaryReader reader)
+            {
+                // No-op.
+            }
+        }
+
+        /// <summary>
+        /// Test class.
+        /// </summary>
+        public class FooClass
+        {
+            // No-op.
+        }
+
+        /// <summary>
+        /// Test factory.
+        /// </summary>
+        public class TestCacheStoreFactory : IFactory<ICacheStore>
+        {
+            /// <summary>
+            /// Creates an instance of the cache store.
+            /// </summary>
+            /// <returns>
+            /// New instance of the cache store.
+            /// </returns>
+            public ICacheStore CreateInstance()
+            {
+                return null;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core.Tests/app.config
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/app.config b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/app.config
new file mode 100644
index 0000000..c290c83
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/app.config
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<configuration>
+    <configSections>
+        <section name="igniteConfiguration" type="Apache.Ignite.Core.IgniteConfigurationSection, Apache.Ignite.Core" />
+        <section name="igniteConfiguration2" type="Apache.Ignite.Core.IgniteConfigurationSection, Apache.Ignite.Core" />
+    </configSections>
+
+    <igniteConfiguration xmlns="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection" gridName="myGrid1">
+        <discoverySpi type="TcpDiscoverySpi">
+            <ipFinder type="TcpDiscoveryStaticIpFinder">
+                <endpoints>
+                    <string>127.0.0.1:47500..47501</string>
+                </endpoints>
+            </ipFinder>
+        </discoverySpi>
+        
+        <cacheConfiguration>
+            <cacheConfiguration name="cacheName" />
+        </cacheConfiguration>
+    </igniteConfiguration>
+
+    <igniteConfiguration2 gridName="myGrid2">
+        <discoverySpi type="TcpDiscoverySpi">
+            <ipFinder type="TcpDiscoveryStaticIpFinder">
+                <endpoints>
+                    <string>127.0.0.1:47500..47501</string>
+                </endpoints>
+            </ipFinder>
+        </discoverySpi>
+
+        <cacheConfiguration>
+            <cacheConfiguration name="cacheName2" />
+        </cacheConfiguration>
+    </igniteConfiguration2>
+
+</configuration>

http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index e2efd0a..d0ef352 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -60,7 +60,9 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
+    <Reference Include="System.configuration" />
     <Reference Include="System.Core" />
+    <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Binary\Package-Info.cs" />
@@ -183,6 +185,7 @@
     <Compile Include="Events\TaskEvent.cs" />
     <Compile Include="GlobalSuppressions.cs" />
     <Compile Include="IgniteConfiguration.cs" />
+    <Compile Include="IgniteConfigurationSection.cs" />
     <Compile Include="Ignition.cs" />
     <Compile Include="IIgnite.cs" />
     <Compile Include="Impl\Binary\BinaryEnum.cs" />
@@ -222,11 +225,13 @@
     <Compile Include="Impl\Collections\MultiValueDictionary.cs" />
     <Compile Include="Impl\Collections\ReadOnlyCollection.cs" />
     <Compile Include="Impl\Collections\ReadOnlyDictionary.cs" />
+    <Compile Include="Impl\Common\BooleanLowerCaseConverter.cs" />
     <Compile Include="Impl\Common\CancelledTask.cs" />
     <Compile Include="Impl\Common\Classpath.cs" />
     <Compile Include="Impl\Common\CopyOnWriteConcurrentDictionary.cs" />
     <Compile Include="Impl\Common\DelegateConverter.cs" />
     <Compile Include="Impl\Common\DelegateTypeDescriptor.cs" />
+    <Compile Include="Impl\Events\EventTypeConverter.cs" />
     <Compile Include="Impl\Common\Fnv1Hash.cs" />
     <Compile Include="Impl\Common\Future.cs" />
     <Compile Include="Impl\Common\FutureConverter.cs" />
@@ -234,10 +239,12 @@
     <Compile Include="Impl\Common\IgniteArgumentCheck.cs" />
     <Compile Include="Impl\Common\IFutureConverter.cs" />
     <Compile Include="Impl\Common\IFutureInternal.cs" />
+    <Compile Include="Impl\Common\IgniteConfigurationXmlSerializer.cs" />
     <Compile Include="Impl\Common\IgniteHome.cs" />
     <Compile Include="Impl\Common\LoadedAssembliesResolver.cs" />
     <Compile Include="Impl\Common\ResizeableArray.cs" />
     <Compile Include="Impl\Common\TypeCaster.cs" />
+    <Compile Include="Impl\Common\TypeStringConverter.cs" />
     <Compile Include="Impl\Compute\Closure\ComputeAbstractClosureTask.cs" />
     <Compile Include="Impl\Compute\Closure\ComputeActionJob.cs" />
     <Compile Include="Impl\Compute\Closure\ComputeFuncJob.cs" />
@@ -434,6 +441,10 @@
   <ItemGroup>
     <None Include="Apache.Ignite.Core.ruleset" />
     <None Include="Apache.Ignite.Core.snk" />
+    <None Include="IgniteConfigurationSection.xsd">
+      <SubType>Designer</SubType>
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
   </ItemGroup>
   <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinarySerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinarySerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinarySerializer.cs
index 23dc811..3f924eb 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinarySerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinarySerializer.cs
@@ -23,17 +23,17 @@ namespace Apache.Ignite.Core.Binary
     public interface IBinarySerializer
     {
         /// <summary>
-        /// Write portalbe object.
+        /// Write binary object.
         /// </summary>
         /// <param name="obj">Object.</param>
-        /// <param name="writer">Poratble writer.</param>
+        /// <param name="writer">Binary writer.</param>
         void WriteBinary(object obj, IBinaryWriter writer);
 
         /// <summary>
         /// Read binary object.
         /// </summary>
         /// <param name="obj">Instantiated empty object.</param>
-        /// <param name="reader">Poratble reader.</param>
+        /// <param name="reader">Binary reader.</param>
         void ReadBinary(object obj, IBinaryReader reader);
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.cs b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.cs
new file mode 100644
index 0000000..51b963e
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.cs
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core
+{
+    using System.Configuration;
+    using System.Text;
+    using System.Xml;
+    using Apache.Ignite.Core.Impl.Common;
+
+    /// <summary>
+    /// Ignite configuration section for app.config and web.config files.
+    /// </summary>
+    public class IgniteConfigurationSection : ConfigurationSection
+    {
+        /// <summary>
+        /// Gets or sets the ignite configuration.
+        /// </summary>
+        /// <value>
+        /// The ignite configuration.
+        /// </value>
+        public IgniteConfiguration IgniteConfiguration { get; private set; }
+
+        /// <summary>
+        /// Reads XML from the configuration file.
+        /// </summary>
+        /// <param name="reader">The reader object, which reads from the configuration file.</param>
+        protected override void DeserializeSection(XmlReader reader)
+        {
+            IgniteArgumentCheck.NotNull(reader, "reader");
+
+            IgniteConfiguration = IgniteConfigurationXmlSerializer.Deserialize(reader);
+        }
+
+        /// <summary>
+        /// Creates an XML string containing an unmerged view of the <see cref="ConfigurationSection" /> 
+        /// object as a single section to write to a file.
+        /// </summary>
+        /// <param name="parentElement">The <see cref="ConfigurationElement" /> 
+        /// instance to use as the parent when performing the un-merge.</param>
+        /// <param name="name">The name of the section to create.</param>
+        /// <param name="saveMode">The <see cref="ConfigurationSaveMode" /> instance 
+        /// to use when writing to a string.</param>
+        /// <returns>
+        /// An XML string containing an unmerged view of the <see cref="ConfigurationSection" /> object.
+        /// </returns>
+        protected override string SerializeSection(ConfigurationElement parentElement, string name, 
+            ConfigurationSaveMode saveMode)
+        {
+            IgniteArgumentCheck.NotNull(parentElement, "parentElement");
+            IgniteArgumentCheck.NotNullOrEmpty(name, "name");
+
+            if (IgniteConfiguration == null)
+                return string.Format("<{0} />", name);
+
+            var sb = new StringBuilder();
+
+            using (var xmlWriter = XmlWriter.Create(sb))
+            {
+                IgniteConfigurationXmlSerializer.Serialize(IgniteConfiguration, xmlWriter, name);
+
+                return sb.ToString();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
new file mode 100644
index 0000000..5181217
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
@@ -0,0 +1,281 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xs:schema id="IgniteConfigurationSection"
+    targetNamespace="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection"
+    elementFormDefault="qualified"
+    xmlns="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection"
+    xmlns:mstns="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+    <xs:element name="igniteConfiguration">
+        <xs:complexType>
+            <xs:all>
+                <xs:element name="binaryConfiguration" minOccurs="0">
+                    <xs:complexType>
+                        <xs:all>
+                            <xs:element name="typeConfigurations" minOccurs="0">
+                                <xs:complexType>
+                                    <xs:sequence>
+                                        <xs:element name="binaryTypeConfiguration">
+                                            <xs:complexType>
+                                                <xs:all>
+                                                    <xs:element name="nameMapper" minOccurs="0">
+                                                        <xs:complexType>
+                                                            <xs:attribute name="type" type="xs:string" use="required" />
+                                                        </xs:complexType>
+                                                    </xs:element>
+                                                    <xs:element name="idMapper" minOccurs="0">
+                                                        <xs:complexType>
+                                                            <xs:attribute name="type" type="xs:string" use="required" />
+                                                        </xs:complexType>
+                                                    </xs:element>
+                                                    <xs:element name="serializer" minOccurs="0">
+                                                        <xs:complexType>
+                                                            <xs:attribute name="type" type="xs:string" use="required" />
+                                                        </xs:complexType>
+                                                    </xs:element>
+                                                </xs:all>
+                                                <xs:attribute name="typeName" type="xs:string" />
+                                                <xs:attribute name="affinityKeyFieldName" type="xs:string" />
+                                                <xs:attribute name="keepDeserialized" type="xs:string" />
+                                                <xs:attribute name="isEnum" type="xs:boolean" />
+                                            </xs:complexType>
+                                        </xs:element>
+                                    </xs:sequence>
+                                </xs:complexType>
+                            </xs:element>
+                            <xs:element name="defaultNameMapper" minOccurs="0">
+                                <xs:complexType>
+                                    <xs:attribute name="type" type="xs:string" use="required" />
+                                </xs:complexType>
+                            </xs:element>
+                            <xs:element name="defaultIdMapper" minOccurs="0">
+                                <xs:complexType>
+                                    <xs:attribute name="type" type="xs:string" use="required" />
+                                </xs:complexType>
+                            </xs:element>
+                            <xs:element name="defaultSerializer" minOccurs="0">
+                                <xs:complexType>
+                                    <xs:attribute name="type" type="xs:string" use="required" />
+                                </xs:complexType>
+                            </xs:element>
+                        </xs:all>
+                        <xs:attribute name="defaultKeepDeserialized" type="xs:boolean" />
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="cacheConfiguration" minOccurs="0">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="cacheConfiguration" maxOccurs="unbounded">
+                                <xs:complexType>
+                                    <xs:all>
+                                        <xs:element name="cacheStoreFactory" minOccurs="0">
+                                            <xs:complexType>
+                                                <xs:attribute name="type" type="xs:string" use="required" />
+                                            </xs:complexType>
+                                        </xs:element>
+                                        <xs:element name="queryEntities" minOccurs="0">
+                                            <xs:complexType>
+                                                <xs:sequence>
+                                                    <xs:element name="queryEntity" maxOccurs="unbounded">
+                                                        <xs:complexType>
+                                                            <xs:all>
+                                                                <xs:element name="fields" minOccurs="0">
+                                                                    <xs:complexType>
+                                                                        <xs:sequence>
+                                                                            <xs:element name="queryField" maxOccurs="unbounded">
+                                                                                <xs:complexType>
+                                                                                    <xs:attribute name="name" type="xs:string" use="required" />
+                                                                                    <xs:attribute name="fieldType" type="xs:string" />
+                                                                                    <xs:attribute name="fieldTypeName" type="xs:string" />
+                                                                                </xs:complexType>
+                                                                            </xs:element>
+                                                                        </xs:sequence>
+                                                                    </xs:complexType>
+                                                                </xs:element>
+                                                                <xs:element name="aliases" minOccurs="0">
+                                                                    <xs:complexType>
+                                                                        <xs:sequence>
+                                                                            <xs:element name="queryAlias" maxOccurs="unbounded">
+                                                                                <xs:complexType>
+                                                                                    <xs:attribute name="fullName" type="xs:string" use="required" />
+                                                                                    <xs:attribute name="alias" type="xs:string" use="required" />
+                                                                                </xs:complexType>
+                                                                            </xs:element>
+                                                                        </xs:sequence>
+                                                                    </xs:complexType>
+                                                                </xs:element>
+                                                                <xs:element name="indexes" minOccurs="0">
+                                                                    <xs:complexType>
+                                                                        <xs:sequence>
+                                                                            <xs:element name="queryIndex" maxOccurs="unbounded">
+                                                                                <xs:complexType>
+                                                                                    <xs:sequence>
+                                                                                        <xs:element name="fields" minOccurs="1">
+                                                                                            <xs:complexType>
+                                                                                                <xs:sequence>
+                                                                                                    <xs:element name="queryIndexField" maxOccurs="unbounded">
+                                                                                                        <xs:complexType>
+                                                                                                            <xs:attribute name="name" type="xs:string" use="required" />
+                                                                                                            <xs:attribute name="isDescending" type="xs:boolean" />
+                                                                                                        </xs:complexType>
+                                                                                                    </xs:element>
+                                                                                                </xs:sequence>
+                                                                                            </xs:complexType>
+                                                                                        </xs:element>
+                                                                                    </xs:sequence>
+                                                                                    <xs:attribute name="name" type="xs:string" />
+                                                                                    <xs:attribute name="indexType" type="xs:string" />
+                                                                                </xs:complexType>
+                                                                            </xs:element>
+                                                                        </xs:sequence>
+                                                                    </xs:complexType>
+                                                                </xs:element>
+                                                            </xs:all>
+                                                            <xs:attribute name="keyTypeName" type="xs:string"/>
+                                                            <xs:attribute name="keyType" type="xs:string" />
+                                                            <xs:attribute name="valueTypeName" type="xs:string" />
+                                                            <xs:attribute name="valueType" type="xs:string" />
+                                                        </xs:complexType>
+                                                    </xs:element>
+                                                </xs:sequence>
+                                            </xs:complexType>
+                                        </xs:element>
+                                    </xs:all>
+                                    <xs:attribute name="name" type="xs:string" />
+                                    <xs:attribute name="writeSynchronizationMode" type="xs:string" />
+                                    <xs:attribute name="evictSynchronized" type="xs:boolean" />
+                                    <xs:attribute name="evictSynchronizedKeyBufferSize" type="xs:int" />
+                                    <xs:attribute name="evictSynchronizedConcurrencyLevel" type="xs:int" />
+                                    <xs:attribute name="evictSynchronizedTimeout" type="xs:string" />
+                                    <xs:attribute name="maxEvictionOverflowRatio" type="xs:decimal" />
+                                    <xs:attribute name="startSize" type="xs:int" />
+                                    <xs:attribute name="loadPreviousValue" type="xs:string" />
+                                    <xs:attribute name="atomicityMode" type="xs:string" />
+                                    <xs:attribute name="atomicWriteOrderMode" type="xs:string" />
+                                    <xs:attribute name="backups" type="xs:int" />
+                                    <xs:attribute name="lockTimeout" type="xs:string" />
+                                    <xs:attribute name="invalidate" type="xs:boolean" />
+                                    <xs:attribute name="rebalanceMode" type="xs:string" />
+                                    <xs:attribute name="rebalanceBatchSize" type="xs:int" />
+                                    <xs:attribute name="enableSwap" type="xs:boolean" />
+                                    <xs:attribute name="maxConcurrentAsyncOperations" type="xs:int" />
+                                    <xs:attribute name="writeBehindEnabled" type="xs:boolean" />
+                                    <xs:attribute name="writeBehindFlushSize" type="xs:int" />
+                                    <xs:attribute name="writeBehindFlushThreadCount" type="xs:int" />
+                                    <xs:attribute name="writeBehindBatchSize" type="xs:int" />
+                                    <xs:attribute name="rebalanceTimeout" type="xs:string" />
+                                    <xs:attribute name="rebalanceDelay" type="xs:string" />
+                                    <xs:attribute name="rebalanceThrottle" type="xs:string" />
+                                    <xs:attribute name="offHeapMaxMemory" type="xs:int" />
+                                    <xs:attribute name="memoryMode" type="xs:string" />
+                                    <xs:attribute name="longQueryWarningTimeout" type="xs:string" />
+                                    <xs:attribute name="sqlEscapeAll" type="xs:boolean" />
+                                    <xs:attribute name="sqlOnheapRowCacheSize" type="xs:int" />
+                                </xs:complexType>
+                            </xs:element>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="jvmOptions" minOccurs="0">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element maxOccurs="unbounded" name="string" type="xs:string" />
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="assemblies" minOccurs="0">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element maxOccurs="unbounded" name="string" type="xs:string" />
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="lifecycleBeans" minOccurs="0">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element maxOccurs="unbounded" name="iLifecycleBean">
+                                <xs:complexType>
+                                    <xs:attribute name="type" type="xs:string" use="required" />
+                                </xs:complexType>
+                            </xs:element>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="discoverySpi" minOccurs="0">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="ipFinder" minOccurs="0">
+                                <xs:complexType>
+                                    <xs:sequence>
+                                        <xs:element name="endpoints" minOccurs="0">
+                                            <xs:complexType>
+                                                <xs:sequence>
+                                                    <xs:element maxOccurs="unbounded" name="string" type="xs:string" />
+                                                </xs:sequence>
+                                            </xs:complexType>
+                                        </xs:element>
+                                    </xs:sequence>
+                                    <xs:attribute name="type" type="xs:string" use="required" />
+                                    <xs:attribute name="localAddress" type="xs:string" />
+                                    <xs:attribute name="multicastGroup" type="xs:string" />
+                                    <xs:attribute name="multicastPort" type="xs:int" />
+                                    <xs:attribute name="addressRequestAttempts" type="xs:int" />
+                                    <xs:attribute name="responseTimeout" type="xs:string" />
+                                    <xs:attribute name="timeToLive" type="xs:byte" />
+                                </xs:complexType>
+                            </xs:element>
+                        </xs:sequence>
+                        <xs:attribute name="socketTimeout" type="xs:string" />
+                        <xs:attribute name="ackTimeout" type="xs:string" />
+                        <xs:attribute name="maxAckTimeout" type="xs:string" />
+                        <xs:attribute name="networkTimeout" type="xs:string" />
+                        <xs:attribute name="joinTimeout" type="xs:string" />
+                        <xs:attribute name="type" type="xs:string" use="required" />
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="includedEventTypes" minOccurs="0">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element maxOccurs="unbounded" name="int" type="xs:string" />
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+            </xs:all>
+            <xs:attribute name="gridName" type="xs:string" />
+            <xs:attribute name="jvmDllPath" type="xs:string" />
+            <xs:attribute name="igniteHome" type="xs:string" />
+            <xs:attribute name="jvmClasspath" type="xs:string" />
+            <xs:attribute name="suppressWarnings" type="xs:boolean" />
+            <xs:attribute name="jvmInitialMemoryMb" type="xs:int" />
+            <xs:attribute name="jvmMaxMemoryMb" type="xs:int" />
+            <xs:attribute name="clientMode" type="xs:boolean" />
+            <xs:attribute name="metricsExpireTime" type="xs:string" />
+            <xs:attribute name="metricsHistorySize" type="xs:int" />
+            <xs:attribute name="metricsLogFrequency" type="xs:string" />
+            <xs:attribute name="metricsUpdateFrequency" type="xs:string" />
+            <xs:attribute name="networkSendRetryCount" type="xs:int" />
+            <xs:attribute name="networkSendRetryDelay" type="xs:string" />
+            <xs:attribute name="networkTimeout" type="xs:string" />
+            <xs:attribute name="workDirectory" type="xs:string" />
+            <xs:attribute name="localhost" type="xs:string" />
+        </xs:complexType>
+    </xs:element>    
+</xs:schema>

http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
index 0549010..70d7422 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
@@ -20,6 +20,7 @@ namespace Apache.Ignite.Core
 {
     using System;
     using System.Collections.Generic;
+    using System.Configuration;
     using System.Diagnostics.CodeAnalysis;
     using System.IO;
     using System.Linq;
@@ -116,6 +117,44 @@ namespace Apache.Ignite.Core
         }
 
         /// <summary>
+        /// Reads <see cref="IgniteConfiguration"/> from first <see cref="IgniteConfigurationSection"/> in the 
+        /// application configuration and starts Ignite.
+        /// </summary>
+        /// <returns>Started Ignite.</returns>
+        public static IIgnite StartFromApplicationConfiguration()
+        {
+            var cfg = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
+
+            var section = cfg.Sections.OfType<IgniteConfigurationSection>().FirstOrDefault();
+
+            if (section == null)
+                throw new ConfigurationErrorsException(
+                    string.Format("Could not find {0} in current application configuration",
+                        typeof(IgniteConfigurationSection).Name));
+
+            return Start(section.IgniteConfiguration);
+        }
+
+        /// <summary>
+        /// Reads <see cref="IgniteConfiguration"/> from application configuration 
+        /// <see cref="IgniteConfigurationSection"/> with specified name and starts Ignite.
+        /// </summary>
+        /// <param name="sectionName">Name of the section.</param>
+        /// <returns>Started Ignite.</returns>
+        public static IIgnite StartFromApplicationConfiguration(string sectionName)
+        {
+            IgniteArgumentCheck.NotNullOrEmpty(sectionName, "sectionName");
+
+            var section = ConfigurationManager.GetSection(sectionName) as IgniteConfigurationSection;
+
+            if (section == null)
+                throw new ConfigurationErrorsException(string.Format("Could not find {0} with name '{1}'",
+                    typeof(IgniteConfigurationSection).Name, sectionName));
+
+            return Start(section.IgniteConfiguration);
+        }
+
+        /// <summary>
         /// Starts Ignite with given configuration.
         /// </summary>
         /// <returns>Started Ignite.</returns>

http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/BooleanLowerCaseConverter.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/BooleanLowerCaseConverter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/BooleanLowerCaseConverter.cs
new file mode 100644
index 0000000..e8cced2
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/BooleanLowerCaseConverter.cs
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Common
+{
+    using System;
+    using System.ComponentModel;
+    using System.Diagnostics.CodeAnalysis;
+    using System.Globalization;
+
+    /// <summary>
+    /// Bollean converter that returns lower-case strings, for XML serialization.
+    /// </summary>
+    internal class BooleanLowerCaseConverter : BooleanConverter
+    {
+        /// <summary>
+        /// Default instance.
+        /// </summary>
+        public static readonly BooleanLowerCaseConverter Instance = new BooleanLowerCaseConverter();
+
+        /// <summary>
+        /// Converts the given value object to the specified type, using the specified context and culture information.
+        /// </summary>
+        /// <param name="context">An <see cref="ITypeDescriptorContext" /> that provides a format context.</param>
+        /// <param name="culture">
+        /// A <see cref="CultureInfo" />. If null is passed, the current culture is assumed.
+        /// </param>
+        /// <param name="value">The <see cref="object" /> to convert.</param>
+        /// <param name="destinationType">
+        /// The <see cref="Type" /> to convert the <paramref name="value" /> parameter to.
+        /// </param>
+        /// <returns>
+        /// An <see cref="object" /> that represents the converted value.
+        /// </returns>
+        [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase")]
+        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "2")]
+        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, 
+            Type destinationType)
+        {
+            if (destinationType == typeof (string))
+                return value.ToString().ToLowerInvariant();
+
+            return base.ConvertTo(context, culture, value, destinationType);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs
new file mode 100644
index 0000000..af25bfa
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs
@@ -0,0 +1,410 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Impl.Common
+{
+    using System;
+    using System.Collections;
+    using System.Collections.Generic;
+    using System.ComponentModel;
+    using System.Configuration;
+    using System.Diagnostics;
+    using System.Diagnostics.CodeAnalysis;
+    using System.Linq;
+    using System.Reflection;
+    using System.Xml;
+    using Apache.Ignite.Core.Impl.Events;
+
+    /// <summary>
+    /// Serializes <see cref="IgniteConfiguration"/> to XML.
+    /// </summary>
+    internal static class IgniteConfigurationXmlSerializer
+    {
+        /** Attribute that specifies a type for abstract properties, such as IpFinder. */
+        private const string TypNameAttribute = "type";
+
+        /** Xmlns. */
+        private const string XmlnsAttribute = "xmlns";
+
+        /** Schema. */
+        private const string Schema = "http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection";
+
+        /// <summary>
+        /// Deserializes <see cref="IgniteConfiguration"/> from specified <see cref="XmlReader"/>.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        /// <returns>Resulting <see cref="IgniteConfiguration"/>.</returns>
+        public static IgniteConfiguration Deserialize(XmlReader reader)
+        {
+            IgniteArgumentCheck.NotNull(reader, "reader");
+
+            var cfg = new IgniteConfiguration();
+
+            if (reader.NodeType == XmlNodeType.Element || reader.Read())
+                ReadElement(reader, cfg);
+
+            return cfg;
+        }
+
+        /// <summary>
+        /// Serializes specified <see cref="IgniteConfiguration" /> to <see cref="XmlWriter" />.
+        /// </summary>
+        /// <param name="configuration">The configuration.</param>
+        /// <param name="writer">The writer.</param>
+        /// <param name="rootElementName">Name of the root element.</param>
+        public static void Serialize(IgniteConfiguration configuration, XmlWriter writer, string rootElementName)
+        {
+            IgniteArgumentCheck.NotNull(configuration, "configuration");
+            IgniteArgumentCheck.NotNull(writer, "writer");
+            IgniteArgumentCheck.NotNullOrEmpty(rootElementName, "rootElementName");
+
+            WriteElement(configuration, writer, rootElementName, typeof(IgniteConfiguration));
+        }
+
+        /// <summary>
+        /// Writes new element.
+        /// </summary>
+        private static void WriteElement(object obj, XmlWriter writer, string rootElementName, Type valueType, 
+            PropertyInfo property = null)
+        {
+            if (valueType == typeof(IgniteConfiguration))
+                writer.WriteStartElement(rootElementName, Schema);  // write xmlns for the root element
+            else
+                writer.WriteStartElement(rootElementName);
+
+            if (IsBasicType(valueType))
+                WriteBasicProperty(obj, writer, valueType, property);
+            else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof (ICollection<>))
+                WriteCollectionProperty(obj, writer, valueType, property);
+            else
+                WriteComplexProperty(obj, writer, valueType);
+
+            writer.WriteEndElement();
+        }
+
+        /// <summary>
+        /// Writes the property of a basic type (primitives, strings, types).
+        /// </summary>
+        [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
+        private static void WriteBasicProperty(object obj, XmlWriter writer, Type valueType, PropertyInfo property)
+        {
+            var converter = GetConverter(property, valueType);
+
+            var stringValue = converter.ConvertToInvariantString(obj);
+
+            writer.WriteString(stringValue);
+        }
+
+        /// <summary>
+        /// Writes the collection property.
+        /// </summary>
+        private static void WriteCollectionProperty(object obj, XmlWriter writer, Type valueType, PropertyInfo property)
+        {
+            var elementType = valueType.GetGenericArguments().Single();
+
+            var elementTypeName = PropertyNameToXmlName(elementType.Name);
+
+            foreach (var element in (IEnumerable)obj)
+                WriteElement(element, writer, elementTypeName, elementType, property);
+        }
+
+        /// <summary>
+        /// Writes the complex property (nested object).
+        /// </summary>
+        [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
+        private static void WriteComplexProperty(object obj, XmlWriter writer, Type valueType)
+        {
+            var props = GetNonDefaultProperties(obj).ToList();
+
+            // Specify type for interfaces and abstract classes
+            if (valueType.IsAbstract)
+                writer.WriteAttributeString(TypNameAttribute, TypeStringConverter.Convert(obj.GetType()));
+
+            // Write attributes
+            foreach (var prop in props.Where(p => IsBasicType(p.PropertyType)))
+            {
+                var converter = GetConverter(prop, prop.PropertyType);
+                var stringValue = converter.ConvertToInvariantString(prop.GetValue(obj, null));
+                writer.WriteAttributeString(PropertyNameToXmlName(prop.Name), stringValue);
+            }
+
+            // Write elements
+            foreach (var prop in props.Where(p => !IsBasicType(p.PropertyType)))
+                WriteElement(prop.GetValue(obj, null), writer, PropertyNameToXmlName(prop.Name),
+                    prop.PropertyType, prop);
+        }
+
+        /// <summary>
+        /// Reads the element.
+        /// </summary>
+        private static void ReadElement(XmlReader reader, object target)
+        {
+            var targetType = target.GetType();
+
+            // Read attributes
+            while (reader.MoveToNextAttribute())
+            {
+                var name = reader.Name;
+                var val = reader.Value;
+
+                SetProperty(target, name, val);
+            }
+
+            // Read content
+            reader.MoveToElement();
+
+            while (reader.Read())
+            {
+                if (reader.NodeType != XmlNodeType.Element)
+                    continue;
+
+                var name = reader.Name;
+                var prop = GetPropertyOrThrow(name, reader.Value, targetType);
+                var propType = prop.PropertyType;
+
+                if (IsBasicType(propType))
+                {
+                    // Regular property in xmlElement form
+                    SetProperty(target, name, reader.ReadString());
+                }
+                else if (propType.IsGenericType && propType.GetGenericTypeDefinition() == typeof (ICollection<>))
+                {
+                    // Collection
+                    ReadCollectionProperty(reader, prop, target);
+                }
+                else
+                {
+                    // Nested object (complex property)
+                    prop.SetValue(target, ReadComplexProperty(reader, propType, prop.Name, targetType), null);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Reads the complex property (nested object).
+        /// </summary>
+        private static object ReadComplexProperty(XmlReader reader, Type propType, string propName, Type targetType)
+        {
+            if (propType.IsAbstract)
+            {
+                var typeName = reader.GetAttribute(TypNameAttribute);
+
+                var derivedTypes = GetConcreteDerivedTypes(propType);
+
+                propType = typeName == null
+                    ? null
+                    : Type.GetType(typeName, false) ?? derivedTypes.FirstOrDefault(x => x.Name == typeName);
+
+                if (propType == null)
+                {
+                    var message = string.Format("'type' attribute is required for '{0}.{1}' property", targetType.Name,
+                        propName);
+
+                    if (typeName != null)
+                    {
+                        message += ", specified type cannot be resolved: " + typeName;
+                    }
+                    else if (derivedTypes.Any())
+                        message += ", possible values are: " + string.Join(", ", derivedTypes.Select(x => x.Name));
+
+                    throw new ConfigurationErrorsException(message);
+                }
+            }
+
+            var nestedVal = Activator.CreateInstance(propType);
+
+            using (var subReader = reader.ReadSubtree())
+            {
+                subReader.Read();  // read first element
+
+                ReadElement(subReader, nestedVal);
+            }
+
+            return nestedVal;
+        }
+
+        /// <summary>
+        /// Reads the collection.
+        /// </summary>
+        private static void ReadCollectionProperty(XmlReader reader, PropertyInfo prop, object target)
+        {
+            var elementType = prop.PropertyType.GetGenericArguments().Single();
+
+            var listType = typeof (List<>).MakeGenericType(elementType);
+
+            var list = (IList) Activator.CreateInstance(listType);
+
+            var converter = IsBasicType(elementType) ? GetConverter(prop, elementType) : null;
+
+            using (var subReader = reader.ReadSubtree())
+            {
+                subReader.Read();  // skip list head
+                while (subReader.Read())
+                {
+                    if (subReader.NodeType != XmlNodeType.Element)
+                        continue;
+
+                    if (subReader.Name != PropertyNameToXmlName(elementType.Name))
+                        throw new ConfigurationErrorsException(
+                            string.Format("Invalid list element in IgniteConfiguration: expected '{0}', but was '{1}'",
+                                PropertyNameToXmlName(elementType.Name), subReader.Name));
+
+                    list.Add(converter != null
+                        ? converter.ConvertFromInvariantString(subReader.ReadString())
+                        : ReadComplexProperty(subReader, elementType, prop.Name, target.GetType()));
+                }
+            }
+
+            prop.SetValue(target, list, null);
+        }
+
+        /// <summary>
+        /// Sets the property.
+        /// </summary>
+        private static void SetProperty(object target, string propName, string propVal)
+        {
+            if (propName == TypNameAttribute || propName == XmlnsAttribute)
+                return;
+
+            var type = target.GetType();
+            var property = GetPropertyOrThrow(propName, propVal, type);
+
+            var converter = GetConverter(property, property.PropertyType);
+
+            var convertedVal = converter.ConvertFromInvariantString(propVal);
+
+            property.SetValue(target, convertedVal, null);
+        }
+
+        /// <summary>
+        /// Gets concrete derived types.
+        /// </summary>
+        private static List<Type> GetConcreteDerivedTypes(Type type)
+        {
+            return type.Assembly.GetTypes().Where(t => t.IsClass && !t.IsAbstract && type.IsAssignableFrom(t)).ToList();
+        }
+
+        /// <summary>
+        /// Gets specified property from a type or throws an exception.
+        /// </summary>
+        private static PropertyInfo GetPropertyOrThrow(string propName, string propVal, Type type)
+        {
+            var property = type.GetProperty(XmlNameToPropertyName(propName));
+
+            if (property == null)
+                throw new ConfigurationErrorsException(
+                    string.Format(
+                        "Invalid IgniteConfiguration attribute '{0}={1}', there is no such property on '{2}'",
+                        propName, propVal, type));
+
+            return property;
+        }
+
+        /// <summary>
+        /// Converts an XML name to CLR name.
+        /// </summary>
+        private static string XmlNameToPropertyName(string name)
+        {
+            Debug.Assert(name.Length > 0);
+
+            if (name == "int")
+                return "Int32";  // allow aliases
+
+            return char.ToUpperInvariant(name[0]) + name.Substring(1);
+        }
+
+        /// <summary>
+        /// Converts a CLR name to XML name.
+        /// </summary>
+        private static string PropertyNameToXmlName(string name)
+        {
+            Debug.Assert(name.Length > 0);
+
+            if (name == "Int32")
+                return "int";  // allow aliases
+
+            return char.ToLowerInvariant(name[0]) + name.Substring(1);
+        }
+
+        /// <summary>
+        /// Determines whether specified type is a basic built-in type.
+        /// </summary>
+        private static bool IsBasicType(Type propertyType)
+        {
+            Debug.Assert(propertyType != null);
+
+            return propertyType.IsValueType || propertyType == typeof(string) || propertyType == typeof(Type);
+        }
+
+        /// <summary>
+        /// Gets converter for a property.
+        /// </summary>
+        private static TypeConverter GetConverter(PropertyInfo property, Type propertyType)
+        {
+            Debug.Assert(property != null);
+            Debug.Assert(propertyType != null);
+
+            if (propertyType.IsEnum)
+                return new GenericEnumConverter(propertyType);
+
+            if (propertyType == typeof (Type))
+                return TypeStringConverter.Instance;
+
+            if (propertyType == typeof(bool))
+                return BooleanLowerCaseConverter.Instance;
+
+            if (property.DeclaringType == typeof (IgniteConfiguration) && property.Name == "IncludedEventTypes")
+                return EventTypeConverter.Instance;
+
+            var converter = TypeDescriptor.GetConverter(propertyType);
+
+            if (converter == null || !converter.CanConvertFrom(typeof(string)) ||
+                !converter.CanConvertTo(typeof(string)))
+                throw new ConfigurationErrorsException("No converter for type " + propertyType);
+
+            return converter;
+        }
+
+        /// <summary>
+        /// Gets properties with non-default value.
+        /// </summary>
+        private static IEnumerable<PropertyInfo> GetNonDefaultProperties(object obj)
+        {
+            Debug.Assert(obj != null);
+
+            return obj.GetType().GetProperties().Where(p => !Equals(p.GetValue(obj, null), GetDefaultValue(p)));
+        }
+
+        /// <summary>
+        /// Gets the default value for a property.
+        /// </summary>
+        private static object GetDefaultValue(PropertyInfo property)
+        {
+            var attr = property.GetCustomAttributes(true).OfType<DefaultValueAttribute>().FirstOrDefault();
+
+            if (attr != null)
+                return attr.Value;
+
+            var propertyType = property.PropertyType;
+
+            if (propertyType.IsValueType)
+                return Activator.CreateInstance(propertyType);
+
+            return null;
+        }
+    }
+}


Mime
View raw message