ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From voze...@apache.org
Subject [42/52] [partial] ignite git commit: IGNITE-1513: Moved .Net.
Date Mon, 21 Sep 2015 14:27:38 GMT
http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/Future.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/Future.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/Future.cs
new file mode 100644
index 0000000..92b4fce
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/Future.cs
@@ -0,0 +1,286 @@
+/*
+ * 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.Generic;
+    using System.Diagnostics.CodeAnalysis;
+    using System.Threading;
+    using System.Threading.Tasks;
+    using Apache.Ignite.Core.Common;
+    using Apache.Ignite.Core.Impl.Portable.IO;
+
+    /// <summary>
+    /// Grid future implementation.
+    /// </summary>
+    [SuppressMessage("ReSharper", "ParameterHidesMember")]
+    [CLSCompliant(false)]
+    public sealed class Future<T> : IFutureInternal, IFuture<T>
+    {
+        /** Converter. */
+        private readonly IFutureConverter<T> _converter;
+
+        /** Result. */
+        private T _res;
+
+        /** Caught cxception. */
+        private Exception _err;
+
+        /** Done flag. */
+        private volatile bool _done;
+
+        /** Listener(s). Either Action or List{Action}. */
+        private object _callbacks;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="converter">Future result marshaller and converter.</param>
+        public Future(IFutureConverter<T> converter = null)
+        {
+            _converter = converter;
+        }
+
+        /** <inheritdoc/> */
+        public bool IsDone
+        {
+            get { return _done; }
+        }
+
+        /** <inheritdoc/> */
+        public T Get()
+        {
+            if (!_done)
+            {
+                lock (this)
+                {
+                    while (!_done)
+                        Monitor.Wait(this);
+                }
+            }
+
+            return Get0();
+        }
+
+        /** <inheritdoc/> */
+        public T Get(TimeSpan timeout)
+        {
+            long ticks = timeout.Ticks;
+
+            if (ticks < 0)
+                throw new ArgumentException("Timeout cannot be negative.");
+
+            if (ticks == 0)
+                return Get();
+
+            if (!_done)
+            {
+                // Fallback to locked mode.
+                lock (this)
+                {
+                    long endTime = DateTime.Now.Ticks + ticks;
+
+                    if (!_done)
+                    {
+                        while (true)
+                        {
+                            Monitor.Wait(this, timeout);
+
+                            if (_done)
+                                break;
+
+                            ticks = endTime - DateTime.Now.Ticks;
+
+                            if (ticks <= 0)
+                                throw new TimeoutException("Timeout waiting for future completion.");
+
+                            timeout = TimeSpan.FromTicks(ticks);
+                        }
+                    }
+                }
+            }
+
+            return Get0();
+        }
+
+        /** <inheritdoc/> */
+        public void Listen(Action callback)
+        {
+            Listen((Action<IFuture<T>>) (fut => callback()));
+        }
+
+        /** <inheritdoc/> */
+        public void Listen(Action<IFuture> callback)
+        {
+            Listen((Action<IFuture<T>>)callback);
+        }
+
+        /** <inheritdoc/> */
+        public void Listen(Action<IFuture<T>> callback)
+        {
+            IgniteArgumentCheck.NotNull(callback, "callback");
+
+            if (!_done)
+            {
+                lock (this)
+                {
+                    if (!_done)
+                    {
+                        AddCallback(callback);
+
+                        return;
+                    }
+                }
+            }
+
+            callback(this);
+        }
+
+        /// <summary>
+        /// Get result or throw an error.
+        /// </summary>
+        private T Get0()
+        {
+            if (_err != null)
+                throw _err;
+
+            return _res;
+        }
+
+        /** <inheritdoc/> */
+        public IAsyncResult ToAsyncResult()
+        {
+            return _done ? CompletedAsyncResult.Instance : new AsyncResult(this);
+        }
+
+        /** <inheritdoc/> */
+        Task<object> IFuture.ToTask()
+        {
+            return Task.Factory.FromAsync(ToAsyncResult(), x => (object) Get());
+        }
+
+        /** <inheritdoc/> */
+        public Task<T> ToTask()
+        {
+            return Task.Factory.FromAsync(ToAsyncResult(), x => Get());
+        }
+
+        /** <inheritdoc/> */
+        object IFuture.Get(TimeSpan timeout)
+        {
+            return Get(timeout);
+        }
+
+        /** <inheritdoc/> */
+        object IFuture.Get()
+        {
+            return Get();
+        }
+
+        /** <inheritdoc /> */
+        public void OnResult(IPortableStream stream)
+        {
+            try
+            {
+                OnResult(_converter.Convert(stream));
+            }
+            catch (Exception ex)
+            {
+                OnError(ex);
+            }
+        }
+
+        /** <inheritdoc /> */
+        public void OnError(Exception err)
+        {
+            OnDone(default(T), err);
+        }
+
+        /** <inheritdoc /> */
+        public void OnNullResult()
+        {
+            OnResult(default(T));
+        }
+
+        /// <summary>
+        /// Set result.
+        /// </summary>
+        /// <param name="res">Result.</param>
+        internal void OnResult(T res)
+        {
+            OnDone(res, null);
+        }
+
+        /// <summary>
+        /// Set future to Done state.
+        /// </summary>
+        /// <param name="res">Result.</param>
+        /// <param name="err">Error.</param>
+        public void OnDone(T res, Exception err)
+        {
+            object callbacks0 = null;
+
+            lock (this)
+            {
+                if (!_done)
+                {
+                    _res = res;
+                    _err = err;
+
+                    _done = true;
+
+                    Monitor.PulseAll(this);
+
+                    // Notify listeners outside the lock
+                    callbacks0 = _callbacks;
+                    _callbacks = null;
+                }
+            }
+
+            if (callbacks0 != null)
+            {
+                var list = callbacks0 as List<Action<IFuture<T>>>;
+
+                if (list != null)
+                    list.ForEach(x => x(this));
+                else
+                    ((Action<IFuture<T>>) callbacks0)(this);
+            }
+        }
+
+        /// <summary>
+        /// Adds a callback.
+        /// </summary>
+        private void AddCallback(Action<IFuture<T>> callback)
+        {
+            if (_callbacks == null)
+            {
+                _callbacks = callback;
+
+                return;
+            }
+
+            var list = _callbacks as List<Action<IFuture<T>>> ??
+                new List<Action<IFuture<T>>> {(Action<IFuture<T>>) _callbacks};
+
+            list.Add(callback);
+
+            _callbacks = list;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/FutureConverter.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/FutureConverter.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/FutureConverter.cs
new file mode 100644
index 0000000..a07d954
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/FutureConverter.cs
@@ -0,0 +1,62 @@
+/*
+ * 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 Apache.Ignite.Core.Impl.Portable;
+    using Apache.Ignite.Core.Impl.Portable.IO;
+
+    /// <summary>
+    /// Marshals and converts future value.
+    /// </summary>
+    internal class FutureConverter<T> : IFutureConverter<T>
+    {
+        /** Marshaller. */
+        private readonly PortableMarshaller _marsh;
+
+        /** Keep portable flag. */
+        private readonly bool _keepPortable;
+
+        /** Converting function. */
+        private readonly Func<PortableReaderImpl, T> _func;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="marsh">Marshaller.</param>
+        /// <param name="keepPortable">Keep portable.</param>
+        /// <param name="func">Converting function.</param>
+        public FutureConverter(PortableMarshaller marsh, bool keepPortable,
+            Func<PortableReaderImpl, T> func = null)
+        {
+            _marsh = marsh;
+            _keepPortable = keepPortable;
+            _func = func ?? (reader => reader.ReadObject<T>());
+        }
+
+        /// <summary>
+        /// Read and convert a value.
+        /// </summary>
+        public T Convert(IPortableStream stream)
+        {
+            var reader = _marsh.StartUnmarshal(stream, _keepPortable);
+
+            return _func(reader);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/FutureType.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/FutureType.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/FutureType.cs
new file mode 100644
index 0000000..0beff04
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/FutureType.cs
@@ -0,0 +1,52 @@
+/*
+ * 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
+{
+    /// <summary>
+    /// Future types.
+    /// </summary>
+    public enum FutureType
+    {
+        /** Future type: byte. */
+        Byte = 1,
+
+        /** Future type: boolean. */
+        Bool = 2,
+
+        /** Future type: short. */
+        Short = 3,
+
+        /** Future type: char. */
+        Char = 4,
+
+        /** Future type: int. */
+        Int = 5,
+
+        /** Future type: float. */
+        Float = 6,
+
+        /** Future type: long. */
+        Long = 7,
+
+        /** Future type: double. */
+        Double = 8,
+
+        /** Future type: object. */
+        Object = 9
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/IFutureConverter.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/IFutureConverter.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/IFutureConverter.cs
new file mode 100644
index 0000000..e07597d
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/IFutureConverter.cs
@@ -0,0 +1,34 @@
+/*
+ * 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 Apache.Ignite.Core.Impl.Portable.IO;
+
+    /// <summary>
+    /// Marshals and converts future value.
+    /// </summary>
+    [CLSCompliant(false)]
+    public interface IFutureConverter<out T>
+    {
+        /// <summary>
+        /// Reads and converts a value.
+        /// </summary>
+        T Convert(IPortableStream stream);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/IFutureInternal.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/IFutureInternal.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/IFutureInternal.cs
new file mode 100644
index 0000000..90f06be
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/IFutureInternal.cs
@@ -0,0 +1,46 @@
+/*
+ * 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 Apache.Ignite.Core.Impl.Portable.IO;
+
+    /// <summary>
+    /// Internal future interface.
+    /// </summary>
+    [CLSCompliant(false)]
+    public interface IFutureInternal
+    {
+        /// <summary>
+        /// Set result from stream.
+        /// </summary>
+        /// <param name="stream">Stream.</param>
+        void OnResult(IPortableStream stream);
+
+        /// <summary>
+        /// Set null result.
+        /// </summary>
+        void OnNullResult();
+
+        /// <summary>
+        /// Set error result.
+        /// </summary>
+        /// <param name="err">Exception.</param>
+        void OnError(Exception err);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/IgniteArgumentCheck.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/IgniteArgumentCheck.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/IgniteArgumentCheck.cs
new file mode 100644
index 0000000..e94c577
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/IgniteArgumentCheck.cs
@@ -0,0 +1,76 @@
+/*
+ * 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.Generic;
+
+    /// <summary>
+    /// Arguments check helpers.
+    /// </summary>
+    public static class IgniteArgumentCheck
+    {
+        /// <summary>
+        /// Throws an ArgumentNullException if specified arg is null.
+        /// </summary>
+        /// <param name="arg">The argument.</param>
+        /// <param name="argName">Name of the argument.</param>
+        public static void NotNull(object arg, string argName)
+        {
+            if (arg == null)
+                throw new ArgumentNullException(argName);
+        }
+
+        /// <summary>
+        /// Throws an ArgumentException if specified arg is null or empty string.
+        /// </summary>
+        /// <param name="arg">The argument.</param>
+        /// <param name="argName">Name of the argument.</param>
+        public static void NotNullOrEmpty(string arg, string argName)
+        {
+            if (string.IsNullOrEmpty(arg))
+                throw new ArgumentException(string.Format("'{0}' argument should not be null or empty.", argName),
+                    argName);
+        }
+
+        /// <summary>
+        /// Throws an ArgumentException if specified arg is null or empty string.
+        /// </summary>
+        /// <param name="collection">The collection.</param>
+        /// <param name="argName">Name of the argument.</param>
+        public static void NotNullOrEmpty<T>(ICollection<T> collection, string argName)
+        {
+            if (collection == null || collection.Count == 0)
+                throw new ArgumentException(string.Format("'{0}' argument should not be null or empty.", argName),
+                    argName);
+        }
+
+        /// <summary>
+        /// Throws an ArgumentException if specified condition is false.
+        /// </summary>
+        /// <param name="condition">Condition.</param>
+        /// <param name="argName">Name of the argument.</param>
+        /// <param name="message">Message.</param>
+        public static void Ensure(bool condition, string argName, string message)
+        {
+            if (!condition)
+                throw new ArgumentException(string.Format("'{0}' argument is invalid: {1}", argName, message), 
+                    argName);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/LoadedAssembliesResolver.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/LoadedAssembliesResolver.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/LoadedAssembliesResolver.cs
new file mode 100644
index 0000000..c158d5c
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/LoadedAssembliesResolver.cs
@@ -0,0 +1,96 @@
+/*
+ * 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.Generic;
+    using System.Diagnostics.CodeAnalysis;
+    using System.Reflection;
+
+    /// <summary>
+    /// Resolves loaded assemblies by name.
+    /// </summary>
+    public class LoadedAssembliesResolver
+    {
+        // The lazy singleton instance.
+        private static readonly Lazy<LoadedAssembliesResolver> LazyInstance = new Lazy<LoadedAssembliesResolver>();
+
+        // Assemblies map.
+        private volatile Dictionary<string, Assembly> _map;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="LoadedAssembliesResolver"/> class.
+        /// </summary>
+        public LoadedAssembliesResolver()
+        {
+            lock (this)
+            {
+                AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad;
+
+                UpdateMap();
+            }
+        }
+
+        /// <summary>
+        /// Handles the AssemblyLoad event of the AppDomain.
+        /// </summary>
+        /// <param name="sender">The source of the event.</param>
+        /// <param name="args">The <see cref="AssemblyLoadEventArgs"/> instance containing the event data.</param>
+        private void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
+        {
+            lock (this)
+            {
+                UpdateMap();
+            }
+        }
+
+        /// <summary>
+        /// Updates the assembly map according to the current list of loaded assemblies.
+        /// </summary>
+        private void UpdateMap()
+        {
+            var assemblies = AppDomain.CurrentDomain.GetAssemblies();
+
+            _map = new Dictionary<string, Assembly>(assemblies.Length);
+
+            foreach (var assembly in assemblies)
+                _map[assembly.FullName] = assembly;
+        }
+
+        /// <summary>
+        /// Gets the singleton instance.
+        /// </summary>
+        public static LoadedAssembliesResolver Instance
+        {
+            get { return LazyInstance.Value; }
+        }
+
+        /// <summary>
+        /// Gets the assembly by name.
+        /// </summary>
+        /// <param name="assemblyName">Name of the assembly.</param>
+        /// <returns>Assembly with specified name, or null.</returns>
+        [SuppressMessage("ReSharper", "InconsistentlySynchronizedField")]
+        public Assembly GetAssembly(string assemblyName)
+        {
+            Assembly asm;
+
+            return _map.TryGetValue(assemblyName, out asm) ? asm : null;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/PortableResultWrapper.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/PortableResultWrapper.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/PortableResultWrapper.cs
new file mode 100644
index 0000000..733bed0
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/PortableResultWrapper.cs
@@ -0,0 +1,68 @@
+/*
+ * 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 Apache.Ignite.Core.Impl.Portable;
+    using Apache.Ignite.Core.Portable;
+
+    /// <summary>
+    /// Simple wrapper over result to handle marshalling properly.
+    /// </summary>
+    internal class PortableResultWrapper : IPortableWriteAware
+    {
+        /** */
+        private readonly object _result;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PortableResultWrapper"/> class.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        public PortableResultWrapper(IPortableReader reader)
+        {
+            var reader0 = (PortableReaderImpl)reader.RawReader();
+
+            _result = PortableUtils.ReadPortableOrSerializable<object>(reader0);
+        }
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="res">Result.</param>
+        public PortableResultWrapper(object res)
+        {
+            _result = res;
+        }
+
+        /// <summary>
+        /// Result.
+        /// </summary>
+        public object Result
+        {
+            get { return _result; }
+        }
+
+        /** <inheritDoc /> */
+        public void WritePortable(IPortableWriter writer)
+        {
+            var writer0 = (PortableWriterImpl) writer.RawWriter();
+
+            writer0.DetachNext();
+            PortableUtils.WritePortableOrSerializable(writer0, Result);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/TypeCaster.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/TypeCaster.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/TypeCaster.cs
new file mode 100644
index 0000000..d0dd2a9
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Common/TypeCaster.cs
@@ -0,0 +1,72 @@
+/*
+ * 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.Linq.Expressions;
+
+    /// <summary>
+    /// Does type casts without extra boxing. 
+    /// Should be used when casting compile-time incompatible value types instead of "(T)(object)x".
+    /// </summary>
+    /// <typeparam name="T">Target type</typeparam>
+    public static class TypeCaster<T>
+    {
+        /// <summary>
+        /// Efficiently casts an object from TFrom to T.
+        /// Does not cause boxing for value types.
+        /// </summary>
+        /// <typeparam name="TFrom">Source type to cast from.</typeparam>
+        /// <param name="obj">The object to cast.</param>
+        /// <returns>Casted object.</returns>
+        public static T Cast<TFrom>(TFrom obj)
+        {
+            return Casters<TFrom>.Caster(obj);
+        }
+
+        /// <summary>
+        /// Inner class serving as a cache.
+        /// </summary>
+        private static class Casters<TFrom>
+        {
+            /// <summary>
+            /// Compiled caster delegate.
+            /// </summary>
+            internal static readonly Func<TFrom, T> Caster = Compile();
+
+            /// <summary>
+            /// Compiles caster delegate.
+            /// </summary>
+            private static Func<TFrom, T> Compile()
+            {
+                if (typeof (T) == typeof (TFrom))
+                {
+                    // Just return what we have
+                    var pExpr = Expression.Parameter(typeof(TFrom));
+                    
+                    return Expression.Lambda<Func<TFrom, T>>(pExpr, pExpr).Compile();
+                }
+
+                var paramExpr = Expression.Parameter(typeof(TFrom));
+                var convertExpr = Expression.Convert(paramExpr, typeof(T));
+
+                return Expression.Lambda<Func<TFrom, T>>(convertExpr, paramExpr).Compile();
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeAbstractClosureTask.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeAbstractClosureTask.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeAbstractClosureTask.cs
new file mode 100644
index 0000000..1a772c2
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeAbstractClosureTask.cs
@@ -0,0 +1,101 @@
+/*
+ * 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.Compute.Closure
+{
+    using System;
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Cluster;
+    using Apache.Ignite.Core.Compute;
+
+    /// <summary>
+    /// Base class for all tasks working with closures.
+    /// </summary>
+    internal abstract class ComputeAbstractClosureTask<TA, T, TR> : IComputeTask<TA, T, TR>
+    {
+        /// <summary>
+        /// This method is called to map or split Ignite task into multiple Ignite jobs. This is the
+        /// first method that gets called when task execution starts.
+        /// </summary>
+        /// <param name="subgrid">Nodes available for this task execution. Note that order of nodes is
+        /// guaranteed to be randomized by container. This ensures that every time you simply iterate
+        /// through Ignite nodes, the order of nodes will be random which over time should result into
+        /// all nodes being used equally.</param>
+        /// <param name="arg">Task execution argument. Can be <c>null</c>. This is the same argument
+        /// as the one passed into <c>ICompute.Execute()</c> methods.</param>
+        /// <returns>
+        /// Map of Ignite jobs assigned to subgrid node. If <c>null</c> or empty map is returned,
+        /// exception will be thrown.
+        /// </returns>
+        /// <exception cref="System.NotSupportedException">Map step should not be called on this task.</exception>
+        public IDictionary<IComputeJob<T>, IClusterNode> Map(IList<IClusterNode> subgrid, TA arg)
+        {
+            throw new NotSupportedException("Map step should not be called on this task.");
+        }
+
+        /// <summary>
+        /// Asynchronous callback invoked every time a result from remote execution is
+        /// received. It is ultimately upto this method to return a policy based
+        /// on which the system will either wait for more results, reduce results
+        /// received so far, or failover this job to another node. See
+        /// <see cref="ComputeJobResultPolicy" /> for more information.
+        /// </summary>
+        /// <param name="res">Received remote Ignite executable result.</param>
+        /// <param name="rcvd">All previously received results. Note that if task class has
+        /// <see cref="ComputeTaskNoResultCacheAttribute" /> attribute, then this list will be empty.</param>
+        /// <returns>
+        /// Result policy that dictates how to process further upcoming job results.
+        /// </returns>
+        public ComputeJobResultPolicy Result(IComputeJobResult<T> res, IList<IComputeJobResult<T>> rcvd)
+        {
+            Exception err = res.Exception();
+
+            if (err != null)
+            {
+                if (err is ComputeExecutionRejectedException || err is ClusterTopologyException || 
+                    err is ComputeJobFailoverException)
+                    return ComputeJobResultPolicy.Failover;
+                
+                throw err;
+            }
+            
+            return Result0(res);
+        }
+
+        /// <summary>
+        /// Reduces (or aggregates) results received so far into one compound result to be returned to
+        /// caller via future.
+        /// <para />
+        /// Note, that if some jobs did not succeed and could not be failed over then the list of
+        /// results passed into this method will include the failed results. Otherwise, failed
+        /// results will not be in the list.
+        /// </summary>
+        /// <param name="results">Received job results. Note that if task class has
+        /// <see cref="ComputeTaskNoResultCacheAttribute" /> attribute, then this list will be empty.</param>
+        /// <returns>
+        /// Task result constructed from results of remote executions.
+        /// </returns>
+        public abstract TR Reduce(IList<IComputeJobResult<T>> results);
+
+        /// <summary>
+        /// Internal result processing routine.
+        /// </summary>
+        /// <param name="res">Result.</param>
+        /// <returns>Policy.</returns>
+        protected abstract ComputeJobResultPolicy Result0(IComputeJobResult<T> res);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeActionJob.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeActionJob.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeActionJob.cs
new file mode 100644
index 0000000..c91a167
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeActionJob.cs
@@ -0,0 +1,83 @@
+/*
+ * 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.Compute.Closure
+{
+    using System;
+    using Apache.Ignite.Core.Compute;
+    using Apache.Ignite.Core.Impl.Portable;
+    using Apache.Ignite.Core.Impl.Resource;
+    using Apache.Ignite.Core.Portable;
+
+    /// <summary>
+    /// System job which wraps over <c>Action</c>.
+    /// </summary>
+    internal class ComputeActionJob : IComputeJob, IComputeResourceInjector, IPortableWriteAware
+    {
+        /** Closure. */
+        private readonly IComputeAction _action;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="action">Action.</param>
+        public ComputeActionJob(IComputeAction action)
+        {
+            _action = action;
+        }
+
+        /** <inheritDoc /> */
+        public object Execute()
+        {
+            _action.Invoke();
+            
+            return null;
+        }
+
+        /** <inheritDoc /> */
+        public void Cancel()
+        {
+            throw new NotSupportedException("Func job cannot be cancelled.");
+        }
+
+        /** <inheritDoc /> */
+        public void Inject(Ignite grid)
+        {
+            ResourceProcessor.Inject(_action, grid);
+        }
+
+        /** <inheritDoc /> */
+        public void WritePortable(IPortableWriter writer)
+        {
+            var writer0 = (PortableWriterImpl)writer.RawWriter();
+
+            writer0.DetachNext();
+            PortableUtils.WritePortableOrSerializable(writer0, _action);
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ComputeActionJob"/> class.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        public ComputeActionJob(IPortableReader reader)
+        {
+            var reader0 = (PortableReaderImpl)reader.RawReader();
+
+            _action = PortableUtils.ReadPortableOrSerializable<IComputeAction>(reader0);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeFuncJob.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeFuncJob.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeFuncJob.cs
new file mode 100644
index 0000000..381c701
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeFuncJob.cs
@@ -0,0 +1,89 @@
+/*
+ * 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.Compute.Closure
+{
+    using System;
+    using Apache.Ignite.Core.Impl.Portable;
+    using Apache.Ignite.Core.Impl.Resource;
+    using Apache.Ignite.Core.Portable;
+
+    /// <summary>
+    /// System job which wraps over <c>Func</c>.
+    /// </summary>
+    internal class ComputeFuncJob : IComputeJob, IComputeResourceInjector, IPortableWriteAware
+    {
+        /** Closure. */
+        private readonly IComputeFunc _clo;
+
+        /** Argument. */
+        private readonly object _arg;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="clo">Closure.</param>
+        /// <param name="arg">Argument.</param>
+        public ComputeFuncJob(IComputeFunc clo, object arg)
+        {
+            _clo = clo;
+            _arg = arg;
+        }
+
+        /** <inheritDoc /> */
+        public object Execute()
+        {
+            return _clo.Invoke(_arg);
+        }
+
+        /** <inheritDoc /> */
+        public void Cancel()
+        {
+            throw new NotSupportedException("Func job cannot be cancelled.");
+        }
+
+        /** <inheritDoc /> */
+        public void Inject(Ignite grid)
+        {
+            ResourceProcessor.Inject(_clo, grid);
+        }
+
+        /** <inheritDoc /> */
+        public void WritePortable(IPortableWriter writer)
+        {
+            PortableWriterImpl writer0 = (PortableWriterImpl) writer.RawWriter();
+
+            writer0.DetachNext();
+            PortableUtils.WritePortableOrSerializable(writer0, _clo);
+
+            writer0.DetachNext();
+            PortableUtils.WritePortableOrSerializable(writer0, _arg);
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ComputeFuncJob"/> class.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        public ComputeFuncJob(IPortableReader reader)
+        {
+            var reader0 = (PortableReaderImpl) reader.RawReader();
+            
+            _clo = PortableUtils.ReadPortableOrSerializable<IComputeFunc>(reader0);
+            _arg = PortableUtils.ReadPortableOrSerializable<object>(reader0);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeMultiClosureTask.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeMultiClosureTask.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeMultiClosureTask.cs
new file mode 100644
index 0000000..dd57f6c
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeMultiClosureTask.cs
@@ -0,0 +1,56 @@
+/*
+ * 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.Compute.Closure
+{
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Compute;
+
+    /// <summary>
+    /// Closure-based task producing multiple jobs and returning a collection of job results.
+    /// </summary>
+    [ComputeTaskNoResultCache]
+    internal class ComputeMultiClosureTask<TA, T, TR> : ComputeAbstractClosureTask<TA, T, TR> 
+        where TR : ICollection<T>
+    {
+        /** Result. */
+        private readonly ICollection<T> _res;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="size">Expected results count.</param>
+        public ComputeMultiClosureTask(int size)
+        {
+            _res = new List<T>(size);
+        }
+
+        /** <inheritDoc /> */
+        protected override ComputeJobResultPolicy Result0(IComputeJobResult<T> res)
+        {
+            _res.Add(res.Data());
+
+            return ComputeJobResultPolicy.Wait;
+        }
+
+        /** <inheritDoc /> */
+        public override TR Reduce(IList<IComputeJobResult<T>> results)
+        {
+            return (TR) _res;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeOutFuncJob.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeOutFuncJob.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeOutFuncJob.cs
new file mode 100644
index 0000000..5f719cd
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeOutFuncJob.cs
@@ -0,0 +1,76 @@
+/*
+ * 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.Compute.Closure
+{
+    using System;
+    using Apache.Ignite.Core.Impl.Portable;
+    using Apache.Ignite.Core.Impl.Resource;
+    using Apache.Ignite.Core.Portable;
+
+    /// <summary>
+    /// System job which wraps over <c>Func</c>.
+    /// </summary>
+    internal class ComputeOutFuncJob : IComputeJob, IComputeResourceInjector, IPortableWriteAware
+    {
+        /** Closure. */
+        private readonly IComputeOutFunc _clo;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="clo">Closure.</param>
+        public ComputeOutFuncJob(IComputeOutFunc clo)
+        {
+            _clo = clo;
+        }
+
+        /** <inheritDoc /> */
+        public object Execute()
+        {
+            return _clo.Invoke();
+        }
+
+        /** <inheritDoc /> */
+        public void Cancel()
+        {
+            throw new NotSupportedException("Func job cannot be cancelled.");
+        }
+
+        /** <inheritDoc /> */
+        public void Inject(Ignite grid)
+        {
+            ResourceProcessor.Inject(_clo, grid);
+        }
+
+        /** <inheritDoc /> */
+        public void WritePortable(IPortableWriter writer)
+        {
+            var writer0 = (PortableWriterImpl) writer.RawWriter();
+
+            writer0.DetachNext();
+            PortableUtils.WritePortableOrSerializable(writer0, _clo);
+        }
+
+        public ComputeOutFuncJob(IPortableReader reader)
+        {
+            var reader0 = (PortableReaderImpl) reader.RawReader();
+
+            _clo = PortableUtils.ReadPortableOrSerializable<IComputeOutFunc>(reader0);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeReducingClosureTask.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeReducingClosureTask.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeReducingClosureTask.cs
new file mode 100644
index 0000000..a84d7ce
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeReducingClosureTask.cs
@@ -0,0 +1,61 @@
+/*
+ * 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.Compute.Closure
+{
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Compute;
+    using Apache.Ignite.Core.Impl.Resource;
+
+    /// <summary>
+    /// Closure-based task producing only one job and thus having only single result.
+    /// </summary>
+    [ComputeTaskNoResultCache]
+    internal class ComputeReducingClosureTask<TA, T, TR> 
+        : ComputeAbstractClosureTask<TA, T, TR>, IComputeResourceInjector
+    {
+        /** Reducer. */
+        private readonly IComputeReducer<T, TR> _rdc;
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="rdc">Reducer.</param>
+        public ComputeReducingClosureTask(IComputeReducer<T, TR> rdc)
+        {
+            _rdc = rdc;
+        }
+
+        /** <inheritDoc /> */
+        protected override ComputeJobResultPolicy Result0(IComputeJobResult<T> res)
+        {
+            return _rdc.Collect(res.Data()) ? ComputeJobResultPolicy.Wait : ComputeJobResultPolicy.Reduce;
+        }
+
+        /** <inheritDoc /> */
+        public override TR Reduce(IList<IComputeJobResult<T>> results)
+        {
+            return _rdc.Reduce();
+        }
+
+        /** <inheritDoc /> */
+        public void Inject(Ignite grid)
+        {
+            ResourceProcessor.Inject(_rdc, grid);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeSingleClosureTask.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeSingleClosureTask.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeSingleClosureTask.cs
new file mode 100644
index 0000000..6e82c9b
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/ComputeSingleClosureTask.cs
@@ -0,0 +1,48 @@
+/*
+ * 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.Compute.Closure
+{
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Compute;
+
+    /// <summary>
+    /// Closure-based task producing only one job and thus having only single result.
+    /// </summary>
+    [ComputeTaskNoResultCache]
+    internal class ComputeSingleClosureTask<TA, T, TR> : ComputeAbstractClosureTask<TA, T, TR> where TR : T
+    {
+        /** Result. */
+        private TR _res;
+
+        /** <inheritDoc /> */
+        protected override ComputeJobResultPolicy Result0(IComputeJobResult<T> res)
+        {
+            _res = (TR) res.Data();
+
+            // No more results are expected at this point, but we prefer not to alter regular
+            // task flow.
+            return ComputeJobResultPolicy.Wait;
+        }
+
+        /** <inheritDoc /> */
+        public override TR Reduce(IList<IComputeJobResult<T>> results)
+        {
+            return _res;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/IComputeResourceInjector.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/IComputeResourceInjector.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/IComputeResourceInjector.cs
new file mode 100644
index 0000000..8d3e8d7
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Closure/IComputeResourceInjector.cs
@@ -0,0 +1,31 @@
+/*
+ * 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.Compute.Closure
+{
+    /// <summary>
+    /// Interface denoting entity which must perform custom resource injection.
+    /// </summary>
+    internal interface IComputeResourceInjector
+    {
+        /// <summary>
+        /// Inject resources.
+        /// </summary>
+        /// <param name="grid">Grid.</param>
+        void Inject(Ignite grid);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Compute.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Compute.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Compute.cs
new file mode 100644
index 0000000..7efabd1
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/Compute.cs
@@ -0,0 +1,213 @@
+/*
+ * 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.Compute
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Diagnostics;
+    using Apache.Ignite.Core.Cluster;
+    using Apache.Ignite.Core.Common;
+    using Apache.Ignite.Core.Compute;
+
+    /// <summary>
+    /// Synchronous Compute facade.
+    /// </summary>
+    internal class Compute : ICompute
+    {
+        /** */
+        private readonly ComputeImpl _compute;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Compute"/> class.
+        /// </summary>
+        /// <param name="computeImpl">The compute implementation.</param>
+        public Compute(ComputeImpl computeImpl)
+        {
+            Debug.Assert(computeImpl != null);
+
+            _compute = computeImpl;
+        }
+
+        /** <inheritDoc /> */
+        public ICompute WithAsync()
+        {
+            return new ComputeAsync(_compute);
+        }
+
+        /** <inheritDoc /> */
+        public bool IsAsync
+        {
+            get { return false; }
+        }
+
+        /** <inheritDoc /> */
+        public IFuture GetFuture()
+        {
+            throw IgniteUtils.GetAsyncModeDisabledException();
+        }
+
+        /** <inheritDoc /> */
+        public IFuture<TResult> GetFuture<TResult>()
+        {
+            throw IgniteUtils.GetAsyncModeDisabledException();
+        }
+
+        /** <inheritDoc /> */
+        public IClusterGroup ClusterGroup
+        {
+            get { return _compute.ClusterGroup; }
+        }
+
+        /** <inheritDoc /> */
+        public ICompute WithNoFailover()
+        {
+            _compute.WithNoFailover();
+
+            return this;
+        }
+
+        /** <inheritDoc /> */
+        public ICompute WithTimeout(long timeout)
+        {
+            _compute.WithTimeout(timeout);
+
+            return this;
+        }
+
+        /** <inheritDoc /> */
+        public ICompute WithKeepPortable()
+        {
+            _compute.WithKeepPortable();
+
+            return this;
+        }
+
+        /** <inheritDoc /> */
+        public T ExecuteJavaTask<T>(string taskName, object taskArg)
+        {
+            return _compute.ExecuteJavaTask<T>(taskName, taskArg);
+        }
+
+        /** <inheritDoc /> */
+        public TR Execute<TA, T, TR>(IComputeTask<TA, T, TR> task, TA taskArg)
+        {
+            return _compute.Execute(task, taskArg).Get();
+        }
+
+        /** <inheritDoc /> */
+        public TR Execute<T, TR>(IComputeTask<T, TR> task)
+        {
+            return _compute.Execute(task, null).Get();
+        }
+
+        /** <inheritDoc /> */
+        public TR Execute<TA, T, TR>(Type taskType, TA taskArg)
+        {
+            return _compute.Execute<TA, T, TR>(taskType, taskArg).Get();
+        }
+
+        public TR Execute<T, TR>(Type taskType)
+        {
+            return _compute.Execute<object, T, TR>(taskType, null).Get();
+        }
+
+        /** <inheritDoc /> */
+        public TR Call<TR>(IComputeFunc<TR> clo)
+        {
+            return _compute.Execute(clo).Get();
+        }
+
+        /** <inheritDoc /> */
+        public TR AffinityCall<TR>(string cacheName, object affinityKey, IComputeFunc<TR> clo)
+        {
+            return _compute.AffinityCall(cacheName, affinityKey, clo).Get();
+        }
+
+        /** <inheritDoc /> */
+        public TR Call<TR>(Func<TR> func)
+        {
+            return _compute.Execute(func).Get();
+        }
+
+        /** <inheritDoc /> */
+        public ICollection<TR> Call<TR>(IEnumerable<IComputeFunc<TR>> clos)
+        {
+            return _compute.Execute(clos).Get();
+        }
+
+        /** <inheritDoc /> */
+        public TR2 Call<TR1, TR2>(IEnumerable<IComputeFunc<TR1>> clos, IComputeReducer<TR1, TR2> rdc)
+        {
+            return _compute.Execute(clos, rdc).Get();
+        }
+
+        /** <inheritDoc /> */
+        public ICollection<TR> Broadcast<TR>(IComputeFunc<TR> clo)
+        {
+            return _compute.Broadcast(clo).Get();
+        }
+
+        /** <inheritDoc /> */
+        public ICollection<TR> Broadcast<T, TR>(IComputeFunc<T, TR> clo, T arg)
+        {
+            return _compute.Broadcast(clo, arg).Get();
+        }
+
+        /** <inheritDoc /> */
+        public void Broadcast(IComputeAction action)
+        {
+            _compute.Broadcast(action).Get();
+        }
+
+        /** <inheritDoc /> */
+        public void Run(IComputeAction action)
+        {
+            _compute.Run(action).Get();
+        }
+
+        /** <inheritDoc /> */
+        public void AffinityRun(string cacheName, object affinityKey, IComputeAction action)
+        {
+            _compute.AffinityRun(cacheName, affinityKey, action).Get();
+        }
+
+        /** <inheritDoc /> */
+        public void Run(IEnumerable<IComputeAction> actions)
+        {
+            _compute.Run(actions).Get();
+        }
+
+        /** <inheritDoc /> */
+        public TR Apply<T, TR>(IComputeFunc<T, TR> clo, T arg)
+        {
+            return _compute.Apply(clo, arg).Get();
+        }
+
+        /** <inheritDoc /> */
+        public ICollection<TR> Apply<T, TR>(IComputeFunc<T, TR> clo, IEnumerable<T> args)
+        {
+            return _compute.Apply(clo, args).Get();
+        }
+
+        /** <inheritDoc /> */
+        public TR2 Apply<T, TR1, TR2>(IComputeFunc<T, TR1> clo, IEnumerable<T> args, IComputeReducer<TR1, TR2> rdc)
+        {
+            return _compute.Apply(clo, args, rdc).Get();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeAsync.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeAsync.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeAsync.cs
new file mode 100644
index 0000000..199afc2
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeAsync.cs
@@ -0,0 +1,261 @@
+/*
+ * 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.Compute
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Diagnostics.CodeAnalysis;
+    using System.Threading;
+    using Apache.Ignite.Core.Cluster;
+    using Apache.Ignite.Core.Common;
+    using Apache.Ignite.Core.Compute;
+
+    /// <summary>
+    /// Asynchronous Compute facade.
+    /// </summary>
+    [SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable")]
+    internal class ComputeAsync : ICompute
+    {
+        /** */
+        protected readonly ComputeImpl Compute;
+
+        /** Current future. */
+        private readonly ThreadLocal<IFuture> _curFut = new ThreadLocal<IFuture>();
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ComputeAsync"/> class.
+        /// </summary>
+        /// <param name="computeImpl">The compute implementation.</param>
+        internal ComputeAsync(ComputeImpl computeImpl)
+        {
+            Compute = computeImpl;
+        }
+
+        /** <inheritDoc /> */
+        public ICompute WithAsync()
+        {
+            return this;
+        }
+
+        /** <inheritDoc /> */
+        public bool IsAsync
+        {
+            get { return true; }
+        }
+
+        /** <inheritDoc /> */
+        public IFuture GetFuture()
+        {
+            return GetFuture<object>();
+        }
+
+        /** <inheritDoc /> */
+        public IFuture<TResult> GetFuture<TResult>()
+        {
+            var fut = _curFut.Value;
+
+            if (fut == null)
+                throw new InvalidOperationException("Asynchronous operation not started.");
+
+            var fut0 = fut as IFuture<TResult>;
+
+            if (fut0 == null)
+                throw new InvalidOperationException(
+                    string.Format("Requested future type {0} is incompatible with current future type {1}",
+                        typeof(IFuture<TResult>), fut.GetType()));
+
+            _curFut.Value = null;
+
+            return fut0;
+        }
+
+        /** <inheritDoc /> */
+        public IClusterGroup ClusterGroup
+        {
+            get { return Compute.ClusterGroup; }
+        }
+
+        /** <inheritDoc /> */
+        public ICompute WithNoFailover()
+        {
+            Compute.WithNoFailover();
+
+            return this;
+        }
+
+        /** <inheritDoc /> */
+        public ICompute WithTimeout(long timeout)
+        {
+            Compute.WithTimeout(timeout);
+
+            return this;
+        }
+
+        /** <inheritDoc /> */
+        public ICompute WithKeepPortable()
+        {
+            Compute.WithKeepPortable();
+
+            return this;
+        }
+        
+        /** <inheritDoc /> */
+        public T ExecuteJavaTask<T>(string taskName, object taskArg)
+        {
+            _curFut.Value = Compute.ExecuteJavaTaskAsync<T>(taskName, taskArg);
+
+            return default(T);
+        }
+
+        /** <inheritDoc /> */
+        public TR Execute<TA, T, TR>(IComputeTask<TA, T, TR> task, TA taskArg)
+        {
+            _curFut.Value = Compute.Execute(task, taskArg);
+
+            return default(TR);
+        }
+
+        /** <inheritDoc /> */
+        public TR Execute<T, TR>(IComputeTask<T, TR> task)
+        {
+            _curFut.Value = Compute.Execute(task, null);
+
+            return default(TR);
+        }
+
+        /** <inheritDoc /> */
+        public TR Execute<TA, T, TR>(Type taskType, TA taskArg)
+        {
+            _curFut.Value = Compute.Execute<TA, T, TR>(taskType, taskArg);
+
+            return default(TR);
+        }
+
+        /** <inheritDoc /> */
+        public TR Execute<T, TR>(Type taskType)
+        {
+            _curFut.Value = Compute.Execute<object, T, TR>(taskType, null);
+
+            return default(TR);
+        }
+
+        /** <inheritDoc /> */
+        public TR Call<TR>(IComputeFunc<TR> clo)
+        {
+            _curFut.Value = Compute.Execute(clo);
+
+            return default(TR);
+        }
+
+        /** <inheritDoc /> */
+        public TR AffinityCall<TR>(string cacheName, object affinityKey, IComputeFunc<TR> clo)
+        {
+            Compute.AffinityCall(cacheName, affinityKey, clo);
+
+            return default(TR);
+        }
+
+        /** <inheritDoc /> */
+        public TR Call<TR>(Func<TR> func)
+        {
+            _curFut.Value = Compute.Execute(func);
+
+            return default(TR);
+        }
+
+        /** <inheritDoc /> */
+        public ICollection<TR> Call<TR>(IEnumerable<IComputeFunc<TR>> clos)
+        {
+            _curFut.Value = Compute.Execute(clos);
+
+            return null;
+        }
+
+        /** <inheritDoc /> */
+        public TR2 Call<TR1, TR2>(IEnumerable<IComputeFunc<TR1>> clos, IComputeReducer<TR1, TR2> rdc)
+        {
+            _curFut.Value = Compute.Execute(clos, rdc);
+
+            return default(TR2);
+        }
+
+        /** <inheritDoc /> */
+        public ICollection<TR> Broadcast<TR>(IComputeFunc<TR> clo)
+        {
+            _curFut.Value = Compute.Broadcast(clo);
+
+            return null;
+        }
+
+        /** <inheritDoc /> */
+        public ICollection<TR> Broadcast<T, TR>(IComputeFunc<T, TR> clo, T arg)
+        {
+            _curFut.Value = Compute.Broadcast(clo, arg);
+
+            return null;
+        }
+
+        /** <inheritDoc /> */
+        public void Broadcast(IComputeAction action)
+        {
+            _curFut.Value = Compute.Broadcast(action);
+        }
+
+        /** <inheritDoc /> */
+        public void Run(IComputeAction action)
+        {
+            _curFut.Value = Compute.Run(action);
+        }
+
+        /** <inheritDoc /> */
+        public void AffinityRun(string cacheName, object affinityKey, IComputeAction action)
+        {
+            Compute.AffinityRun(cacheName, affinityKey, action);
+        }
+
+        /** <inheritDoc /> */
+        public void Run(IEnumerable<IComputeAction> actions)
+        {
+            _curFut.Value = Compute.Run(actions);
+        }
+
+        /** <inheritDoc /> */
+        public TR Apply<T, TR>(IComputeFunc<T, TR> clo, T arg)
+        {
+            _curFut.Value = Compute.Apply(clo, arg);
+
+            return default(TR);
+        }
+
+        /** <inheritDoc /> */
+        public ICollection<TR> Apply<T, TR>(IComputeFunc<T, TR> clo, IEnumerable<T> args)
+        {
+            _curFut.Value = Compute.Apply(clo, args);
+
+            return null;
+        }
+
+        /** <inheritDoc /> */
+        public TR2 Apply<T, TR1, TR2>(IComputeFunc<T, TR1> clo, IEnumerable<T> args, IComputeReducer<TR1, TR2> rdc)
+        {
+            _curFut.Value = Compute.Apply(clo, args, rdc);
+
+            return default(TR2);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeFunc.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeFunc.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeFunc.cs
new file mode 100644
index 0000000..a971418
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Compute/ComputeFunc.cs
@@ -0,0 +1,119 @@
+/*
+ * 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.Compute
+{
+    using System;
+    using System.Reflection;
+    using Apache.Ignite.Core.Compute;
+    using Apache.Ignite.Core.Impl.Common;
+    using Apache.Ignite.Core.Impl.Portable;
+    using Apache.Ignite.Core.Impl.Resource;
+    using Apache.Ignite.Core.Portable;
+    using Apache.Ignite.Core.Resource;
+
+    /// <summary>
+    /// Non-generic version of IComputeFunc{T}.
+    /// </summary>
+    internal interface IComputeFunc : IComputeFunc<object, object>
+    {
+        // No-op
+    }
+
+    /// <summary>
+    /// Wraps generic func into a non-generic for internal usage.
+    /// </summary>
+    internal class ComputeFuncWrapper : IComputeFunc, IPortableWriteAware
+    {
+        /** */
+        private readonly object _func;
+
+        /** */
+        private readonly Func<object, object, object> _invoker;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ComputeFuncWrapper" /> class.
+        /// </summary>
+        /// <param name="func">The function to wrap.</param>
+        /// <param name="invoker">The function invoker.</param>
+        public ComputeFuncWrapper(object func, Func<object, object> invoker)
+        {
+            _func = func;
+
+            _invoker = (target, arg) => invoker(arg);
+        }
+
+        /** <inheritDoc /> */
+        public object Invoke(object arg)
+        {
+            try
+            {
+                return _invoker(_func, arg);
+            }
+            catch (TargetInvocationException ex)
+            {
+                throw ex.InnerException;
+            }
+        }
+
+        /** <inheritDoc /> */
+        public void WritePortable(IPortableWriter writer)
+        {
+            var writer0 = (PortableWriterImpl)writer.RawWriter();
+
+            writer0.DetachNext();
+            PortableUtils.WritePortableOrSerializable(writer0, _func);
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ComputeFuncWrapper"/> class.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        public ComputeFuncWrapper(IPortableReader reader)
+        {
+            var reader0 = (PortableReaderImpl)reader.RawReader();
+
+            _func = PortableUtils.ReadPortableOrSerializable<object>(reader0);
+
+            _invoker = DelegateTypeDescriptor.GetComputeFunc(_func.GetType());
+        }
+
+        /// <summary>
+        /// Injects the Ignite instance.
+        /// </summary>
+        [InstanceResource]
+        public void InjectIgnite(IIgnite ignite)
+        {
+            // Propagate injection
+            ResourceProcessor.Inject(_func, (IgniteProxy) ignite);
+        }
+    }    
+    
+    /// <summary>
+    /// Extension methods for IComputeFunc{T}.
+    /// </summary>
+    internal static class ComputeFuncExtensions
+    {
+        /// <summary>
+        /// Convert to non-generic wrapper.
+        /// </summary>
+        public static IComputeFunc ToNonGeneric<T, TR>(this IComputeFunc<T, TR> func)
+        {
+            return new ComputeFuncWrapper(func, x => func.Invoke((T) x));
+        }
+    }
+}


Mime
View raw message