在对象的现有实例上进行鸭子输入/动态代理 [英] Duck typing / dynamic proxies on existing instances of objects

查看:96
本文介绍了在对象的现有实例上进行鸭子输入/动态代理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个对象传递到我们的库中,并经过各种过程.当这些对象经过各个阶段并到达另一端时,我需要为其添加一些附加信息-我想是一种动态装饰器模式,除了添加其他属性而不是更改现有行为外.

我希望使用LinFu或Castle创建一个动态代理,并在对象上实现一个附加接口来存储它.知道扩展接口的组件可以强制转换和访问它,而那些不扩展的组件则可以忽略,因为底层类型没有改变.

但是,我没有意识到所有这些机制都假定您可以控制类型的初始创建点,而我没有.

有人对我如何更好地解决这个问题有建议吗?

非常感谢

解决方案

这不能完全解决您的情况,但是如何使用充当对象周围装饰器的DynamicObject实现呢?它将允许您访问原始对象以及其他属性.有点像ExpandoObject,但从您自己的实例数据开始.

类似这样的东西:

public class Expando : DynamicObject
{
    public dynamic Instance;
    Dictionary<string, dynamic> ExtraProperties = new Dictionary<string, dynamic>();

    public Expando(object instance)
    {
        Instance = instance;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        try
        {
            result = ReflectionUtils.GetProperty(Instance, binder.Name);
            return true;
        }
        catch
        {
            if (ExtraProperties.Keys.Contains(binder.Name))
            {
                result = ExtraProperties[binder.Name];
                return true;
            }
        }

        result = null;
        return false;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        try
        {
            ReflectionUtils.SetProperty(Instance, binder.Name, value);
        }
        catch (Exception ex)
        {
            ExtraProperties[binder.Name] = value;
        }

        return true;
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        try
        {
            result = ReflectionUtils.CallMethod(Instance, binder.Name, args);
            return true;
        }
        catch
        {}

        result = null;
        return false;
    }
}

不幸的是,它不能解决您对键入/接口的强烈要求,考虑到此处的反射用法,性能也不会达到最佳(来自 解决方案

This doesn't address your scenario exactly but how about using a DynamicObject implementation that acts as a decorator around your object? It would allow you to access the original object as well as additional properties. Sort of like ExpandoObject but starting out with your own instance data.

Something like this:

public class Expando : DynamicObject
{
    public dynamic Instance;
    Dictionary<string, dynamic> ExtraProperties = new Dictionary<string, dynamic>();

    public Expando(object instance)
    {
        Instance = instance;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        try
        {
            result = ReflectionUtils.GetProperty(Instance, binder.Name);
            return true;
        }
        catch
        {
            if (ExtraProperties.Keys.Contains(binder.Name))
            {
                result = ExtraProperties[binder.Name];
                return true;
            }
        }

        result = null;
        return false;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        try
        {
            ReflectionUtils.SetProperty(Instance, binder.Name, value);
        }
        catch (Exception ex)
        {
            ExtraProperties[binder.Name] = value;
        }

        return true;
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        try
        {
            result = ReflectionUtils.CallMethod(Instance, binder.Name, args);
            return true;
        }
        catch
        {}

        result = null;
        return false;
    }
}

It doesn't address your strong typing/interface requirement unfortunately though and performance isn't going to be the greatest given the Reflection usage here (from https://github.com/RickStrahl/Westwind.Utilities/blob/master/Westwind.Utilities/Utilities/ReflectionUtils.cs)

这篇关于在对象的现有实例上进行鸭子输入/动态代理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆