现有对象实例上的鸭子类型/动态代理

发布于 2024-12-14 19:17:11 字数 301 浏览 0 评论 0原文

我有一个对象被移交给我们的图书馆并通过了各种流程。当这些对象通过各个阶段并从另一端出来时,我需要向它们附加一些附加信息 - 我猜,除了添加附加属性而不是更改现有行为之外,这是一种动态装饰器模式。

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

然而,我没有意识到所有这些机制都假设您可以控制类型最初创建的点 - 但我没有。

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

非常感谢

I have an object handed into our library and passed through various processes. I need to attach some additional information to these objects as they pass through various stages and out the other end - a kind of dynamic decorator pattern, I guess, except adding additional properties rather than changing existing behaviour.

I was hoping to use LinFu or Castle to create a dynamic proxy and implement an additional interface on the object to store this. Components that know about the extended interface could cast and access it - whilst those that are not are oblivious, as the underlying type has not changed.

However, I hadn't appreciated that all these mechanisms assume you have control over the point at which the type is initially created - which I don't.

Does anyone have suggestions on how I could better approach this?

Many thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浮云落日 2024-12-21 19:17:11

这并不能完全解决您的场景,但是使用 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;
    }
}

不幸的是,它并没有满足您强大的类型/接口要求,并且考虑到此处的反射使用,性能不会是最好的(来自 https://github.com/RickStrahl/Westwind.Utilities/blob/master/Westwind.Utilities/Utilities/ReflectionUtils.cs

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)

万水千山粽是情ミ 2024-12-21 19:17:11

看起来有点矫枉过正...只需创建一个仅包含您的“额外”属性的新类。定义一个静态Dictionary。当“知情”的组件想要查看某个对象的扩展属性时,它们只需在字典中查找该对象即可。

Seems like overkill... just create a new class containing just your "extra" properties. The define a static Dictionary<MainClass,ExtensionsClass>. When your components "in the know" want to look at the extended properties for an object, they just look that object up in the dictionary.

溺深海 2024-12-21 19:17:11

您想使用这里的方法 在 c# 中运行时向类型化对象添加 Expando 属性

这样就不会出现内存泄漏

You want to use the approach from here adding expando properties to a typed object at runtime in c#

That way you won't get memory leaks

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文