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 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 { [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 { 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 { 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 { 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 { 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 { 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() { 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); } } }