簡體   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