从扩展方法动态添加新对象属性

时间:2015-06-11 14:36:18

标签: c# .net extension-methods

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

我有一些基类

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中进行一些计算,并将结果保存为PropertyC AObjectAObject默认没有PropertyC,因此我想动态添加它。我发现要使用动态属性我必须使用ExpandoObject,但不确定我是否看到它在这里可以使用...

所以,主要的问题是它是一个好的场景还是我必须考虑别的什么?

1 个答案:

答案 0 :(得分:3)

您需要从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的获取者和设置者来访问_members,或者您可以在Try(Get|Set)Member中处理此案例。将这些属性添加到_member开启了迭代这些成员的可能性。