Last active
December 10, 2015 09:38
-
-
Save thecodejunkie/4415623 to your computer and use it in GitHub Desktop.
Dynamic member resolution chaining
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace DynamicMemberChaining | |
{ | |
using System; | |
using System.Dynamic; | |
using Xunit; | |
public interface ITextResource | |
{ | |
string this[string key] { get; } | |
} | |
public class DefaultTextResource : ITextResource | |
{ | |
public string this[string key] | |
{ | |
get { return "Returned from resource, for key: " + key; } | |
} | |
} | |
public class TextResourceFinder : DynamicObject | |
{ | |
private readonly ITextResource textResource; | |
public TextResourceFinder(ITextResource textResource) | |
{ | |
this.textResource = textResource; | |
} | |
public override bool TryGetMember(GetMemberBinder binder, out object result) | |
{ | |
result = new MemberChainer(binder.Name, this.textResource); | |
return true; | |
} | |
private class MemberChainer : DynamicObject | |
{ | |
private string memberName; | |
private readonly ITextResource textResource; | |
public MemberChainer(string memberName, ITextResource resource) | |
{ | |
this.memberName = memberName; | |
this.textResource = resource; | |
} | |
public override bool TryGetMember(GetMemberBinder binder, out object result) | |
{ | |
this.memberName = | |
string.Concat(this.memberName, ".", binder.Name); | |
result = this; | |
return true; | |
} | |
public override bool TryConvert(ConvertBinder binder, out object result) | |
{ | |
if (binder.ReturnType == typeof (string)) | |
{ | |
result = this.textResource[this.memberName]; | |
return true; | |
} | |
throw new InvalidOperationException("Cannot cast dynamic member access to anything else than a string."); | |
} | |
} | |
} | |
public class Fixture | |
{ | |
[Fact] | |
public void Should_FactMethodName() | |
{ | |
// Given | |
var textResource = new DefaultTextResource(); | |
dynamic finder = new TextResourceFinder(textResource); | |
// When | |
var result = finder.foo.bar.other; | |
// Then | |
Assert.Equal("Returned from resource, for key: foo.bar.other", (string)result); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment