Closed coder-zzo closed 9 years ago
The ReturnType on the binder is always going to be object
. It's how the DLR works with C#. But there are two ways to go about this in your case.
Using a Dynamitey.DynamicObjects.BaseObject
https://github.com/ekonbenefits/dynamitey/blob/master/Dynamitey/DynamicObjects/BaseObject.cs
Then you can call TryTypeForName(string binderName, out Type type) from inside TryGetMember
and get the return type.
OR
You can write another DynamicObject
to wrap the result of TryGetMember
with TryConvert
overridden.
public override bool TryConvert(System.Dynamic.ConvertBinder binder, out object result)
{
result = Convert.ChangeType(_target, binder.Type)
return true;
}
The reason for this is that the DLR for c# does this in two passes, invokes the method as if it returns object
and then invokes the cast to the intended type dynamically.
Thanks for your help, I used second way. Although added a Class, but the code looks better than original.
private class ConfigImpl<T> : DynamicObject
{
private class AutoConvertSupport : DynamicObject
{
private readonly object _value;
public AutoConvertSupport(object value)
{
_value = value;
}
public override bool TryConvert(ConvertBinder binder, out object result)
{
result = Convert.ChangeType(_value, binder.Type);
return true;
}
}
private readonly Dictionary<string, string> _section;
public ConfigImpl(string section)
{
_section = Sections[section];
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (_section.ContainsKey(binder.Name) == false)
throw new ArgumentException("Config not found");
result = new AutoConvertSupport(_section[binder.Name]);
return true;
}
}
This's my usage:
public interface IMailClientConfig { string Host { get; } int SmtpPort { get; } }
IMailClientConfig r = new ConfigImpl("MailClient").ActLike();
var str = r.Host; // Working fine.
var num=r.SmtpPort; // Throw RuntimeBinderException. Can't cast string to int, see above
Now i only can make a 'patch' , but that's isn't beautiful coding.
private class ConfigImpl : DynamicObject
{
private readonly Dictionary<string, string> _section;
private readonly Dictionary<string, Type> _props;