简体   繁体   English

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

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

Is it possible to do something like this: 是否可以做这样的事情:

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

Can it be done while still using auto-implemented getters and setters? 在仍然使用自动实现的getter和setter的同时可以做到吗?

Edit: I am trying to build a game using an "Entity Component" system, each "thing" in the game is an entity, and each entity is made up of components. 编辑:我正在尝试使用“实体组件”系统构建游戏,游戏中的每个“事物”都是一个实体,并且每个实体都是由组件组成的。 Components are things like drawing to the screen, processing input, physics stuff, etc. One key in my plan for building these components is that all configuration of them will be done using their properties. 组件是诸如绘制到屏幕上,处理输入,物理学的东西之类的东西。我构建这些组件的计划中的一个关键是,将使用它们的属性来完成它们的所有配置。 Then I want to be able to save, load, duplicate, and edit on the fly these Components in a generic way. 然后,我希望能够以通用方式实时保存,加载,复制和编辑这些组件。 If the meat of the components is in their properties, then to save we just save the value of each property, same for loading and duplication. 如果组件的属性在其属性中,那么要保存,我们只需保存每个属性的值,对于加载和复制来说都是相同的。 And when I add a new component, getting it to have all of these desired behaviors will be as simple as adding all the getters, setters, and property names, to a list. 而且,当我添加一个新组件时,使其具有所有这些所需的行为就像将所有getter,setter和属性名称添加到列表一样简单。 This will also allow me to build a generic editor which will allow me to edit any property on the fly. 这也将允许我构建一个通用编辑器,该编辑器将允许我即时编辑任何属性。 (Yes I realize I will have to handle all string properties differently from all int properties but I am only planning on using a handful of types.) I hope that made sense and I am open to suggestions on alternate designs. (是的,我意识到我将不得不以与所有int属性不同的方式来处理所有字符串属性,但我只打算使用少数类型。)我希望这是有道理的,并且我愿意接受有关替代设计的建议。

As some comments hint, this will do the job: 就像一些评论所暗示的,这可以完成工作:

  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, use an action as a delegate. IE,使用动作作为委托。

In this case though, it seems a bit superfluous, why do you need this functionality? 但是,在这种情况下,似乎有点多余,为什么需要此功能?

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

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

Isn't the property clearer in it's purpose? 目的不是更清晰吗?

Some time ago I made this objectification of a property which allows passing it around, getting and setting the value. 前一段时间,我对属性进行了对象化,该属性允许传递它,获取和设置值。

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

Together with a helpful extension method 连同有用的扩展方法

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

Created and used like this 像这样创建和使用

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

And used in a method 并用于一种方法

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

EDIT: To get the name and path (one level) of the property you can add this method to the PropHandle-class 编辑:要获取属性的名称和路径(一级),可以将此方法添加到PropHandle类中

public string GetSimplePath()
{
    return this.owner.GetType().Name + this.propertyInfo.Name;
}

flindeberg's answer is the simplest and the clearest. 弗林德伯格的答案是最简单,最清晰的。 But, if you're dead-set (no pun intended) on using the setter method without wrapping it in a lambda, this can be done. 但是,如果您使用setter方法而僵硬(无双关) ,而无需将其包装在lambda中,则可以这样做。 It's just not the easiest thing in the whole world. 这并不是全世界最简单的事情。

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