如何实现自定义动态拦截器?

时间:2018-01-05 21:23:09

标签: c# .net expandoobject

我试图想办法利用动态类型来提供其成员的自然使用,但最终来自Dictionary<string, string>对象。但是,我希望能够定义如何解析给定属性的规则。这可能吗?

我想要这样的东西。

var dynamicCollection = new MyDyanmicType();
dynamicCollection.Build(/*some dictionary*/); // or just implement an implicit operator
dynamicCollection.MemberProperty; // <-- this should let me search the dictionary how I want for some form of the string "MemberProperty"
dynamicCollection.PropertyThatDoesntExist; // <-- this should give me an opportunity to exhaust my resolution and throw back a custom exception that I choose

用例是我有一些由产品管理人员在数据库中动态设置的字段。不幸的是,我需要防范人为错误的波动。鉴于上述情况,有人可能会输入memberProperty,Member Property等,因此我需要控制如何查找声明的成员,同时保持对普通POCO的清洁使用。

我面临的问题是我有一个样本字典代码的TON,我试图摆脱它,这将允许我摆脱一些相当讨厌和冗长的运行时检查。

1 个答案:

答案 0 :(得分:0)

这比我想象的要容易得多。解决方案看起来像这样。

public class AddOnBag : DynamicObject
{
    private Dictionary<string, string> _addOns;

    public static AddOnBag BuildBag(Dictionary<string, string> dict)
    {
        var bag = new AddOnBag {_addOns = dict};

        return bag;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        var addOn = LookupAddOn(binder.Name);

        result = addOn.Value;

        return addOn.Key != null;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        var addOn = LookupAddOn(binder.Name);

        if (addOn.Key == null)
        {
            return false;
        }

        _addOns[addOn.Key] = value.ToString();

        return true;
    }

    private KeyValuePair<string, string> LookupAddOn(string name)
    {
        var addOn = _addOns.FirstOrDefault(pair =>
        {
            var stripped = pair.Key.Replace(" ", string.Empty);
            var attempted = name;

            return string.Equals(stripped, attempted, StringComparison.OrdinalIgnoreCase);
        });

        return addOn;
    }
}

另外,事实证明,微软提供的示例非常接近于此。

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/walkthrough-creating-and-using-dynamic-objects

用法只需要dynamic关键字。另外,如果向您创建的类添加方法,CLR足够智能,可以将调用路由到预期的方法,而不是TryGetMemberTryInvokeMember