Skip to content

Instantly share code, notes, and snippets.

@xerxesb
Last active December 11, 2015 20:18
Show Gist options
  • Save xerxesb/4654224 to your computer and use it in GitHub Desktop.
Save xerxesb/4654224 to your computer and use it in GitHub Desktop.
First run at a solution to the Call Recording/Ordering kata
using System;
using System.Collections.Generic;
using System.Diagnostics;
using NUnit.Framework;
using Shouldly;
using System.Linq;
namespace MethodInfos
{
public class Formatter
{
public static string DoIt(List<Call> list)
{
list.Tap((x, i) => x.CallOrder = i)
.Distinct(new TargetComparer())
.Each((c, i) =>
{
c.InstanceNumber = i + 1;
list.Where(x => x.Target == c.Target)
.Each((c2, i2) => c2.InstanceNumber = c.InstanceNumber);
});
var callsByTargetType = list
.GroupBy(call => call.Target.GetType())
.Select(targets => new {
targets.Key,
HasMoreThanOneInstanceOfType = targets.Distinct(new TargetComparer()).Count() > 1
});
if (callsByTargetType.Any(x => x.HasMoreThanOneInstanceOfType))
{
return String.Join("\r\n", list.Select(x => String.Format("{0}@{1}", x.InstanceNumber, x.MemberCall)));
}
return String.Join("\r\n", list.Select(x => x.MemberCall));
}
}
public class TargetComparer : IEqualityComparer<Call>
{
[DebuggerStepThrough]
public bool Equals(Call x, Call y)
{
return x.Target == y.Target;
}
[DebuggerStepThrough]
public int GetHashCode(Call obj)
{
return obj.Target.GetHashCode();
}
}
public class A { }
public class B { }
[TestFixture]
public class MethodInfoTests
{
[Test]
public void SingleItemShouldDisplaySingleCall()
{
var list = new List<Call> { CreateCall(new A(), "Foo.Bar") };
var result = Formatter.DoIt(list);
result.ShouldBe("Foo.Bar");
}
[Test]
public void MultipleCallsOfTheSameObjectShouldDisplayMultipleCalls()
{
var a = new A();
var list = new List<Call> { CreateCall(a, "Foo.Bar"), CreateCall(a, "Foo.Baz") };
var result = Formatter.DoIt(list);
result.ShouldBe("Foo.Bar\r\nFoo.Baz");
}
[Test]
public void MultipleCallsOfDifferentObjectsShouldDisplayMultipleCalls()
{
var a = new A();
var b = new B();
var list = new List<Call> { CreateCall(a, "Foo.Bar"), CreateCall(b, "Guff.Wot") };
var result = Formatter.DoIt(list);
result.ShouldBe("Foo.Bar\r\nGuff.Wot");
}
[Test]
public void MultipleCallsOfDifferentInstancesOfSameTypeShouldDisplayMultipleCallsWithPrefix()
{
var a1 = new A();
var a2 = new A();
var list = new List<Call> { CreateCall(a1, "Foo.Bar"), CreateCall(a2, "Foo.Bar") };
var result = Formatter.DoIt(list);
result.ShouldBe("1@Foo.Bar\r\n2@Foo.Bar");
}
[Test]
public void TheTchepak()
{
var a = new A();
var b = new A();
var c = new B();
/*
Calls = [ (a, Foo.Bar), (b, Foo.Zap), (c, List.ToString), (a, Foo.Bongo) ]
Output:
1@Foo.Bar
2@Foo.Zap
3@List.ToString
1@Foo.Bongo
*/
var list = new List<Call>
{
CreateCall(a, "Foo.Bar"),
CreateCall(b, "Foo.Zap"),
CreateCall(c, "List.ToString"),
CreateCall(a, "Foo.Bongo")
};
var result = Formatter.DoIt(list);
result.ShouldBe(@"1@Foo.Bar
2@Foo.Zap
3@List.ToString
1@Foo.Bongo");
}
[Test]
public void MultipleCallsDisDifferentInstancesOfDifferentTypesShouldDisplayMultipleCallsWithPrefix()
{
var a1 = new A();
var a2 = new A();
var b1 = new B();
var b2 = new B();
var list = new List<Call>()
{
CreateCall(a1, "Foo.Bar"),
CreateCall(a2, "Foo.Bar"),
CreateCall(b1, "Baz.Wak"),
CreateCall(a1, "Foooey.Bor"),
CreateCall(b2, "Fup.Wuz"),
CreateCall(b1, "Baz.Wuz"),
CreateCall(a1, "Foooey.Baz")
};
var result = Formatter.DoIt(list);
result.ShouldBe(@"1@Foo.Bar
2@Foo.Bar
3@Baz.Wak
1@Foooey.Bor
4@Fup.Wuz
3@Baz.Wuz
1@Foooey.Baz");
}
private static Call CreateCall(object a, string methodInfo)
{
return new Call(a, methodInfo);
}
}
public class Call
{
protected bool Equals(Call other)
{
return Equals(_target, other._target) && string.Equals(_memberCall, other._memberCall);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Call) obj);
}
public override int GetHashCode()
{
unchecked
{
return ((_target != null ? _target.GetHashCode() : 0)*397) ^ (_memberCall != null ? _memberCall.GetHashCode() : 0);
}
}
private readonly object _target;
private readonly string _memberCall;
public Call(object target, string memberCall)
{
_target = target;
_memberCall = memberCall;
}
public object Target { get { return _target; } }
public string MemberCall { get { return _memberCall; } }
public int CallOrder { get; set; }
public int InstanceNumber { get; set; }
public override string ToString()
{
return string.Format("MemberCall: {0}, Target: {1}, CallOrder: {2}, InstanceNumber: {3}", MemberCall, Target, CallOrder, InstanceNumber);
}
}
}
@xerxesb
Copy link
Author

xerxesb commented Jan 28, 2013

Also need these IEnumerable extensions:

    public static class EnumerableExtensions
    {
        [DebuggerStepThrough]
        public static void Each<T>(this IEnumerable<T> list, Action<T, int> action)
        {
            var i = 0;
            foreach (var v in list)
            {
                action(v, i);
                i++;
            }
        }

        [DebuggerStepThrough]
        public static IEnumerable<T> Tap<T>(this IEnumerable<T> list, Action<T, int> action)
        {
            var enumerable = list.ToArray();
            enumerable.Each(action);
            return enumerable;
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment