Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added DelegateUtility.Cast. Closes #6.

  • Loading branch information...
commit 1dbe3074c93d440fce879feea9016a6765ae3e2c 1 parent f43bc87
@bgrainger bgrainger authored
View
55 src/Logos.Utility/DelegateUtility.cs
@@ -0,0 +1,55 @@
+
+using System;
+
+namespace Logos.Utility
+{
+ /// <summary>
+ /// Provides methods for manipulating delegates.
+ /// </summary>
+ /// <remarks>See <a href="http://code.logos.com/blog/2008/07/casting_delegates.html">Casting delegates</a>.</remarks>
+ public static class DelegateUtility
+ {
+ /// <summary>
+ /// Casts the specified delegate to the specified type.
+ /// </summary>
+ /// <param name="source">The delegate to cast.</param>
+ /// <returns>A delegate of the specified type which, when invoked, executes
+ /// the specified delegate.</returns>
+ /// <remarks>This method uses the <b>CreateDelegate</b> method of
+ /// <see cref="Delegate" /> to create a new delegate from an existing delegate.
+ /// Use this method to cast a delegate from one type to another, where the delegate types
+ /// have exactly the same parameter types and return type.</remarks>
+ public static T Cast<T>(Delegate source) where T : class
+ {
+ return Cast(source, typeof(T)) as T;
+ }
+
+ /// <summary>
+ /// Casts the specified delegate to the specified type.
+ /// </summary>
+ /// <param name="source">The delegate to cast.</param>
+ /// <param name="type">The type of delegate to which to cast.</param>
+ /// <returns>A delegate of the specified type which, when invoked, executes
+ /// the specified delegate.</returns>
+ /// <remarks>This method uses the <b>CreateDelegate</b> method of
+ /// <see cref="Delegate" /> to create a new delegate from an existing delegate.
+ /// Use this method to cast a delegate from one type to another, where the delegate types
+ /// have exactly the same parameter types and return type.</remarks>
+ public static Delegate Cast(Delegate source, Type type)
+ {
+ if (source == null)
+ return null;
+
+ Delegate[] delegates = source.GetInvocationList();
+ if (delegates.Length == 1)
+ return Delegate.CreateDelegate(type,
+ delegates[0].Target, delegates[0].Method);
+
+ Delegate[] delegatesDest = new Delegate[delegates.Length];
+ for (int nDelegate = 0; nDelegate < delegates.Length; nDelegate++)
+ delegatesDest[nDelegate] = Delegate.CreateDelegate(type,
+ delegates[nDelegate].Target, delegates[nDelegate].Method);
+ return Delegate.Combine(delegatesDest);
+ }
+ }
+}
View
1  src/Logos.Utility/Logos.Utility.csproj
@@ -52,6 +52,7 @@
<ItemGroup>
<Compile Include="ComponentModel\NotifyPropertyChangedUtility.cs" />
<Compile Include="DateTimeUtility.cs" />
+ <Compile Include="DelegateUtility.cs" />
<Compile Include="DictionaryUtility.cs" />
<Compile Include="DisposableService.cs" />
<Compile Include="DisposableUtility.cs" />
View
61 tests/Logos.Utility.Tests/DelegateUtilityTests.cs
@@ -0,0 +1,61 @@
+
+using NUnit.Framework;
+
+namespace Logos.Utility.Tests
+{
+ [TestFixture]
+ public class DelegateUtilityTests
+ {
+ [SetUp]
+ public void SetUp()
+ {
+ m_n = 1;
+ }
+
+ [Test]
+ public void SimpleCastTest()
+ {
+ Calc calc = Add;
+ Calculate calculate = DelegateUtility.Cast<Calculate>(calc);
+ Assert.That(calculate(2), Is.EqualTo(3));
+ }
+
+ [Test]
+ public void MulticastCastTest()
+ {
+ Calc calc = Add;
+ calc += Subtract;
+ Calculate calculate = DelegateUtility.Cast<Calculate>(calc);
+ Assert.That(calculate(2), Is.EqualTo(1));
+ }
+
+ [Test]
+ public void NullCastTest()
+ {
+ Calc calc = null;
+ Calculate calculate = DelegateUtility.Cast<Calculate>(calc);
+ Assert.That(calculate, Is.Null);
+ }
+
+ private delegate int Calc(int x);
+
+ private delegate int Calculate(int x);
+
+ private int Add(int x)
+ {
+ return m_n += x;
+ }
+
+ private int Subtract(int x)
+ {
+ return m_n -= x;
+ }
+
+ private static int Add(int x, int y)
+ {
+ return x + y;
+ }
+
+ int m_n;
+ }
+}
View
1  tests/Logos.Utility.Tests/Logos.Utility.Tests.csproj
@@ -49,6 +49,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="DelegateUtilityTests.cs" />
<Compile Include="ReadOnlyStreamTests.cs" />
<Compile Include="RebasedStreamTests.cs" />
<Compile Include="DateTimeUtilityTests.cs" />
Please sign in to comment.
Something went wrong with that request. Please try again.