2

是否有可能做这样的事情:

class Foo
{
  public delegate void Setter(float value);
  public float Mass { get; set; }

  public Foo()
  {
    Setter massSetter = new Setter(Mass.set);
    // massSetter would be stored somewhere and used later
  }
}

可以在仍然使用自动实现的 getter 和 setter 的同时完成吗?

编辑:我正在尝试使用“实体组件”系统构建游戏,游戏中的每个“事物”都是一个实体,每个实体都由组件组成。组件是诸如在屏幕上绘制、处理输入、物理东西等之类的东西。我构建这些组件的计划中的一个关键是它们的所有配置都将使用它们的属性来完成。然后我希望能够以通用方式即时保存、加载、复制和编辑这些组件。如果组件的核心在于它们的属性,那么为了保存我们只需保存每个属性的值,对于加载和复制也是如此。当我添加一个新组件时,让它拥有所有这些所需的行为就像将所有 getter、setter 和属性名称添加到一个列表中一样简单。这也将允许我构建一个通用编辑器,它允许我即时编辑任何属性。(是的,我意识到我必须以不同于所有 int 属性的方式处理所有字符串属性,但我只计划使用少数类型。)我希望这是有道理的,我愿意接受有关替代设计的建议。

4

3 回答 3

3

正如一些评论暗示的那样,这将完成这项工作:

  class Foo
  {
      public delegate void Setter(float value);
      public float Mass { get; set; }

      public Foo()
      {
          Setter massSetter = x => Mass = x;
          // massSetter would be stored somewhere and used later
      }
  }

IE,使用一个动作作为委托。

不过在这种情况下,这似乎有点多余,为什么需要这个功能?

var f = new Foo();
f.Mass = 1.0d; // What you do with the property

theSetter(1.0d); // What you can do now

财产的目的不是更清楚吗?

于 2013-09-13T06:39:15.433 回答
2

前段时间我做了一个属性的对象化,它允许传递它,获取和设置值。

using System;
using System.Linq.Expressions;
using System.Reflection;

public class PropHandle<TOwner, TProperty>
{
    private TOwner owner;
    private PropertyInfo propertyInfo;

    public PropHandle(TOwner owner, Expression<Func<TOwner, TProperty>> propertyExpression)
    {
        this.owner = owner;

        var memberExpression = (MemberExpression)propertyExpression.Body;
        this.propertyInfo = (PropertyInfo)memberExpression.Member;
    }

    public TProperty Get()
    {
        return (TProperty)this.propertyInfo.GetValue(this.owner, null);
    }

    public void Set(TProperty value)
    {
        this.propertyInfo.SetValue(this.owner, value, null);
    }
}

连同有用的扩展方法

public static PropHandle<TOwner, TProperty> PropHandle<TOwner, TProperty>(this TOwner owner, Expression<Func<TOwner, TProperty>> propertyExpression)
{
    return new PropHandle<TOwner, TProperty>(owner, propertyExpression);
}

像这样创建和使用

var myProp = this.PropHandle(x => x.Mass);
myProp.Set(12);

并在一个方法中使用

public void MyMethod<TOwner>(PropHandle<TOwner, float> massProperty)
{
    massProperty.Set(123);
}

编辑: 要获取属性的名称和路径(一级),您可以将此方法添加到 PropHandle 类

public string GetSimplePath()
{
    return this.owner.GetType().Name + this.propertyInfo.Name;
}
于 2013-09-13T06:55:16.380 回答
1

弗林德伯格的回答是最简单最清楚的。但是,如果您在使用 setter 方法而不将其包装在 lambda 中时死心塌地(没有双关语),则可以这样做。这不是世界上最简单的事情。

using System;
using System.Linq.Expressions;
using System.Reflection;

public Action<TProperty> GetSetterAction(TSource target,
     Expression<Func<TSource, TProperty>> propertyExpression)
{
    var memberExpression = propertyExpression.Body as MemberExpression;
    if (memberExpression == null)
    {
        throw new ArgumentException(@"propertyExpression must express a single
            member of a type.", "propertyExpression");
    }

    var propertyInfo = memberExpression.Member as PropertyExpression;
    if (propertyInfo == null)
    {
        throw new ArgumentException(@"propertyExpression must express a single
           property of a type.", "propertyExpression");
    }

    var setMethodInfo = propertyInfo.GetSetMethod();
    if (setMethodInfo == null)
    {
        throw new ArgumentException(@"propertyExpression must express a single
            writeable property of a type.", "propertyExpression");
    }

    var setMethodDelegate = setMethodInfo.CreateDelegate(
        typeof(Action<TProperty>), target);

    return (Action<TProperty>)(object)setMethodDelegate;
}
于 2013-09-13T06:55:05.323 回答