繁体   English   中英

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

[英]In C# can I create a delegate instance to an auto-implemented property accessor?

是否可以做这样的事情:

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

就像一些评论所暗示的,这可以完成工作:

  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

目的不是更清晰吗?

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

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;
}

弗林德伯格的答案是最简单,最清晰的。 但是,如果您使用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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM