![](/img/trans.png)
[英]Can I define a custom getter for a C# auto-implemented property (a.k.a. auto backing field)?
[英]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.