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

How to implement a custom dynamic interceptor?

我正在想办法利用动态类型来提供其成员的自然使用,但它最终源自 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

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

我面临的问题是我有一大堆样板字典代码,我正试图摆脱它,这将使我摆脱一些相当讨厌和冗长的运行时检查。

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

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;
    }
}

此外,事实证明,Microsoft 提供了一个非常接近于此的示例。

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

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