拦截动态调用以避免RuntimeBinderException

时间:2016-01-20 13:12:37

标签: c# dynamic runtimeexception

我想拦截对动态类型的调用,以避免在调用的方法或属性不存在时出现RuntimeBinderException。 例如:

class Foo {
    bool IsFool{ get; set; }
}
...
dynamic d = new Foo();
bool isFool = d.IsFoo; //works fine
bool isSpecial = d.IsSpecial; //RuntimeBinderException

我想要做的是在调用时创建不存在的属性,或者只返回null。

编辑:我正在尝试的项目是配置文件阅读器。所以我希望这可以避免尝试catch或检查cofiguration文件的每个属性是否存在。

4 个答案:

答案 0 :(得分:3)

我没有看到任何特殊方式,而不是try .. catch阻止处理

try 
{
  bool isSpecial = d.IsSpecial;
  return isSpecial;
}
catch(RuntimeBinderException)
{
  // do something else
  return false;
}

(或)使用System.Reflection命名空间

        bool isSpecial = typeof(Foo)
                         .GetProperties()
                         .Select(p => p.Name == "IsSpecial").Count() > 0 
                         ? d.IsSpecial : false;

根据您的帖子编辑;不确定这有多优雅,但您可以在AppSettingApp.Config文件中定义Web.Config元素,例如

<configuration>
  <appSettings>
    <add key="IsFool" value="Foo"/>
    <add key="Display" value="Foo"/>
  </appSettings>
</configuration>

然后可以阅读以验证成员是否存在,然后相应地调用

        dynamic d = new Foo();

        bool isSpecial = System.Configuration.ConfigurationManager.AppSettings
                         .AllKeys.Contains("IsSpecial") 
                         ? d.IsSpecial : false;

答案 1 :(得分:1)

异常通常需要花费很多时间来检查属性是否存在:

public static bool HasProperty(this object obj, string propertyName)
{
    return obj.GetType().GetProperty(propertyName) != null;
}

答案 2 :(得分:0)

在这里找到答案:https://stackoverflow.com/a/1110504/818088
我必须延长DynamicObject并覆盖TryInvokeMember

答案 3 :(得分:0)

最简单的方法是将其转换为JSON动态对象:

public static class JsonExtensions
{
    public static dynamic ToJson(this object input) => 
         System.Web.Helpers.Json.Decode(System.Web.Helpers.Json.Encode(input));

    static int Main(string[] args) {
         dynamic d = new Foo() { IsFool = true }.ToJson();
         Console.WriteLine(d.IsFool); //prints True
         Console.WriteLine(d.IsSpecial ?? "null"); //prints null
    }
}

class Foo
{
    public bool IsFool { get; set; }
}