![](/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.