在C#中,我可以为自动实现的属性访问器创建委托实例吗?

时间:2013-09-13 06:25:16

标签: c# properties delegates

是否可以做这样的事情:

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属性的方式处理所有字符串属性,但我只计划使用少数类型。)我希望这是有道理的,我愿意接受有关替代设计的建议。

3 个答案:

答案 0 :(得分: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

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

答案 1 :(得分: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;
}

答案 2 :(得分: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;
}