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

Mat*_*ero 3 .net c# dynamic c#-4.0

我们假设我有以下课程:

public class Person {
    public string Name { get; set; }
    public string Surname { get; set; }
    public string FullName {
        get {
            return Name + " " + Surname;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

以下块:

Person person = new Person();
person.Name = "Matt";
person.Surname = "Smith";
return person.FullName;
Run Code Online (Sandbox Code Playgroud)

会回来的Matt Smith.

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

代码如下所示:

dynamic person = new ExpandoObject();
person.Name = "Matt";
person.Surname = "Smith";
Run Code Online (Sandbox Code Playgroud)

但这就是我被困的地方.如何覆盖get新FullName属性的访问者?

我可以实现创建新方法的相同效果:

person.GetFullName = (Func<string>)(() => {
      return person.Name + " " + person.Surname;
});
Run Code Online (Sandbox Code Playgroud)

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

person.GetFullName();
Run Code Online (Sandbox Code Playgroud)

编辑

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

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

person.FullName.get = (Func<string>)(() => {
     return person.Name + " " + person.Surname;
});
Run Code Online (Sandbox Code Playgroud)

然后,像这样调用:

Console.WriteLine(person.FullName); //Prints out "Matt Smith"
Run Code Online (Sandbox Code Playgroud)

Luk*_*keH 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);
}
Run Code Online (Sandbox Code Playgroud)