【问题标题】:Adding new object property dynamically from extension method从扩展方法动态添加新对象属性
【发布时间】:2015-08-27 07:56:36
【问题描述】:

这是我的场景...我想要一些基类,并有一些该类的扩展方法,这些方法可能托管在不同的程序集中。根据添加到项目中的程序集,应计算并存储不同的属性。

我有一些基类

public class AObject
{
    public string PropertyA { get; set; }
    public int PropertyB { get; set; }
}

并且对这个类有一些扩展方法

public static class AObjectExtensions
{
    public static void DoSomething(this AObject a, string value)
    {
        a.PropertyC = value;
    }
}

我想得到什么,我想在扩展方法DoSomething 中进行一些计算,并将结果保存为PropertyCAObject 中。 AObject 默认没有PropertyC,所以我想动态添加。我发现要使用动态属性,我必须使用ExpandoObject,但不确定我是否看到它可以在这里使用...

所以,主要问题是这是一个好的场景还是我必须考虑其他事情?

【问题讨论】:

  • 是否有可能在您调用DoSomething 的情况下,您可以保证拥有一个CObject 类型的对象,该对象派生自AObject 并且上面有PropertyC?对我来说这听起来不是一个好场景,如果你可以使用正确类型的派生对象,那将是更可取的(当然我不知道这是否可行)。不过我的想法是,如果你在一个代码知道PropertyC 存在的地方,它必须对对象有足够的了解,你可以保证它是CObject...
  • 我想避免继承...主要思想是拥有一些基础对象并实现一组扩展,这些扩展在计算与对象相关的不同类型的信息方面做一些工作。
  • 很公平。正如我所说,我不知道你想要做什么的细节。如果您不打算使用继承,那么乍一看 ExpandoObject 似乎是您最好的选择。我注意到一个答案是建议 DynamicObject 这导致我 stackoverflow.com/questions/3565481/… 这表明 expando 更简单,因此如果它完成这项工作可能是我的选择。
  • @Chris:您的链接指向任务调度程序 api。你确定这是正确的吗?
  • @Verarind:不是。希望是现在。 :) 感谢您指出这一点(也在我的编辑窗口中!)

标签: c# .net extension-methods


【解决方案1】:

你需要从DynamicObject继承你的对象:

public class AObject : DynamicObject
{
    public string PropertyA { get; set; }

    public int PropertyB { get; set; }

    #region Dynamic Part

    private readonly Dictionary<string, object> _members = new Dictionary<string, object>();

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        this._members[binder.Name] = value;
        return true;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return this._members.TryGetValue(binder.Name, out result) || base.TryGetMember(binder, out result);
    }

    public override IEnumerable<string> GetDynamicMemberNames()
    {
        return this._members.Keys;
    }

    #endregion
}

您的扩展方法必须更改为:

public static class AObjectExtensions
{
    public static void DoSomething(this AObject a, string value)
    {
        ((dynamic)a).PropertyC = value;
    }
}

您可以使用GetDynamicMemberNames() 遍历所有动态成员,如果AObject 提供访问this._members 的索引器或getter 方法,则您可以访问所有动态值。

编辑: 使用此解决方案可能会出现问题。我没有测试它。 ((dynamic)a).PropertyA 可能被 Try(Get|Set)Member 隐藏。如果是这样,您可以更改PropertyAProprertyB 的getter 和setter 以访问_members,或者您可以在Try(Get|Set)Member 中处理这种情况。将这些属性添加到 _member 也开启了迭代这些成员的可能性。

【讨论】:

  • 需要注意的是,动态属性不会显示在 Intellisense 中,因此任何使用该对象的人都必须知道它在那里。
  • 是的 - 我认为这很清楚。如果您使用的是 Resharper,它能够以相同的方法将动态属性添加到智能感知 - 可能甚至更多。
  • 酷!谢谢你,维拉!看来这就是我需要的!
猜你喜欢
  • 1970-01-01
  • 2011-07-15
  • 2021-02-02
  • 1970-01-01
  • 2020-07-08
  • 2019-08-29
  • 2021-10-13
  • 1970-01-01
相关资源
最近更新 更多