如何覆盖动态对象属性的get访问器

时间:2015-04-28 15:15:50

标签: c# .net c#-4.0 dynamic

假设我有以下课程:

public class Person {
    public string Name { get; set; }
    public string Surname { get; set; }
    public string FullName {
        get {
            return Name + " " + Surname;
        }
    }
}

以下栏目:

Person person = new Person();
person.Name = "Matt";
person.Surname = "Smith";
return person.FullName;

会返回Matt Smith

让我们将Person类型更改为动态ExpandoObject

代码如下所示:

dynamic person = new ExpandoObject();
person.Name = "Matt";
person.Surname = "Smith";

但是我被困在哪里。如何覆盖新get属性的FullName访问者?

我可以达到创建新方法的相同效果:

person.GetFullName = (Func<string>)(() => {
      return person.Name + " " + person.Surname;
});

但是这最终会得到一个方法而不是一个属性,因此称之为:

person.GetFullName();

修改

请注意,我不想知道如何定义或创建新的动态属性。我想知道如何覆盖或定义动态属性的get访问器。

我认为代码可以是这样的:

person.FullName.get = (Func<string>)(() => {
     return person.Name + " " + person.Surname;
});

然后,像这样调用:

Console.WriteLine(person.FullName); //Prints out "Matt Smith"

4 个答案:

答案 0 :(得分:7)

dynamic person = new GetterExpando();
person.Name = "Matt";
person.Surname = "Smith";
person.FullName = new GetterExpando.Getter(x => x.Name + " " + x.Surname);

Console.WriteLine(person.FullName);  // Matt Smith

// ...

public sealed class GetterExpando : DynamicObject
{
    private readonly Dictionary<string, object> _data = new Dictionary<string, object>();

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

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        object value;
        if (_data.TryGetValue(binder.Name, out value))
        {
            var getter = value as Getter;
            result = (getter == null) ? value : getter(this);
            return true;
        }
        return base.TryGetMember(binder, out result);
    }

    public delegate object Getter(dynamic target);
}

答案 1 :(得分:2)

public class SampleDynamicObject : DynamicObject
{
    Dictionary<string, Func<dynamic, object>> customFieldHandlers = new Dictionary<string, Func<dynamic, object>>();

    Dictionary<string, object> values = new Dictionary<string, object>();

    public void Get(string property, Func<dynamic, object> handler)
    {
        customFieldHandlers.Add(property, handler);
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (customFieldHandlers.ContainsKey(binder.Name))
        {
            result = customFieldHandlers[binder.Name](this);
            return true;
        }

        result = values[binder.Name];
        return true;
    }

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


dynamic sampleObject = new SampleDynamicObject();

        sampleObject.Get("FullName", (Func<dynamic, object>)((o) => 
        {
            dynamic obj = o;
            return o.Name + " " + o.Surname; 
        }));

答案 2 :(得分:1)

试试吧

 public class MyDynamic : DynamicObject
{
    private Dictionary<string,object> obj = new Dictionary<string, object>();
    public Func<string,dynamic,object> PropertyResolver { get; set; }
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (obj.ContainsKey(binder.Name))
        {
            result =  obj[binder.Name];
            return true;
        }

        if (PropertyResolver != null)
        {
            var actResult = PropertyResolver(binder.Name, this);
            result = actResult;
            return true;
        }

        return base.TryGetMember(binder, out result);
    }

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

 static void Main(string[] args)
    {
        dynamic person = new MyDynamic();
        person.Name = "Matt";
        person.Surname = "Smith";
        person.PropertyResolver = (Func<string, dynamic, object>)
            ((string name, dynamic me) => { return name == "FullName" ? me.Name + me.Surname : "";  });
Console.WriteLine(person.FullName);
}

答案 3 :(得分:0)

public class SampleDynamicObject : DynamicObject
{
    Dictionary<string, object> values = new Dictionary<string, object>();

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (binder.Name == "Fullname")
        {
            result = values["Name"] + " " + values["Surname"];
            return true;
        }

        result = values[binder.Name];

        return true;
    }

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