0

改写了问题。向下滚动查看原文

好吧,也许我应该给你全貌。我有很多类看起来像这样:

public class Movement : Component
{
    private Vector3 linearVelocity;
    public Vector3 LinearVelocity
    {
        get
        {
            return linearVelocity;
        }
        set
        {
            if (value != linearVelocity)
            {
                linearVelocity = value;
                ComponentChangedEvent<Movement>.Invoke(this, "LinearVelocity");
            }
        }
    }

    // other properties (e.g. AngularVelocity), which are declared exactly
    // the same way as above
}

还有一些名为 Transform、Mesh、Collider、Appearance 等的类,它们都派生自Component并且除了属性之外什么都没有,这些属性都是如上所述声明的。这里重要的是调用ComponentChangedEvent. 一切都很完美,但我一直在寻找一种方法,我不必一次又一次地为每个属性重写相同的逻辑。

我看了一下here,并喜欢使用泛型属性的想法。我想出的看起来像这样:

public class ComponentProperty<TValue, TOwner>
{
    private TValue _value;

    public TValue Value
    {
        get
        {
            return _value;
        }
        set
        {
            if (!EqualityComparer<TValue>.Default.Equals(_value, value))
            {
                _value = value;
                ComponentChangedEvent<TOwner>.Invoke(
                    /*get instance of the class which declares value (e.g. Movement instance)*/,
                    /*get name of property where value comes from (e.g. "LinearVelocity") */);
            }
        }
    }

    public static implicit operator TValue(ComponentProperty<TValue, TOwner> value)
    {
        return value.Value;
    }

    public static implicit operator ComponentProperty<TValue, TOwner>(TValue value)
    {
        return new ComponentProperty<TValue, TOwner> { Value = value };
    }
}

然后我会这样使用它:

public class Movement : Component
{
    public ComponentProperty<Vector3, Movement> LinearVelocity { get; set; }
    public ComponentProperty<Vector3, Movement> AngularVelocity { get; set; }
}

但我无法获得 LinearVelocity 来自的实例,也无法将其命名为字符串。所以我的问题是,如果这一切都是可能的......

但似乎我别无选择,只能像以前一样继续这样做,手动为每个属性编写此逻辑。

原始问题:

从属性中获取声明类的实例

我有一个带有属性的类:

public class Foo
{
    public int Bar { get; set; }
}

在另一种情况下,我有这样的事情:

Foo fooInstance = new Foo();
DoSomething(fooInstance.Bar);

然后,DoSomething我需要fooInstance从一无所有中得到parameter。从上下文来看,可以假设没有任何整数被传递到DoSomething中,而只是 int 的公共属性。

public void DoSomething(int parameter)
{
    // need to use fooInstance here as well,
    // and no, it is not possible to just pass it in as another parameter
}

这有可能吗?使用反射,或者可能是属性上的自定义属性Bar

4

4 回答 4

3

为什么你只想向 DoSomething 发送一个属性,将整个对象发送给它:),所以它会变成,

DoSomething(fooInstance);

然后,您的函数将接受对象而不是参数。您可以使用此函数的重载来确保旧代码不会中断。

于 2012-04-20T16:40:33.477 回答
2

有几种方法可以处理实施INotifyPropertyChanged。您正在做几乎相同的事情,只是您没有实现接口并以不同的方式引发事件。但所有解决方案也适用于您。

  1. 像您一样,使用字符串参数调用方法:OnPropertyChanged("Property")
  2. 使用使用以下属性的 lambda 调用方法:OnPropertyChanged(() => Property)。这样做的好处是它在编译时检查拼写错误和重构友好。
  3. 使用调用者信息注入属性的名称:OnPropertyChanged(). 这将在 C# 5 中工作。
  4. 使用 Castle DynamicProxy 之类的东西在运行时创建一个派生类,它将为您调用该方法。这意味着您需要创建您的属性virtual,并且您只需要通过 Castle 创建类的实例。
  5. 使用 AOP 框架在编译后修改属性的代码以调用该方法。
于 2012-04-20T17:22:21.927 回答
0

没有办法fooInstanceparameter. parameter是按值传递的,只是 的值的副本,fooInstance.Bar不再与fooInstance

话虽这么说,显而易见的解决方案是这样DoSomething

public void DoSomething(Foo parameter)
{
    // need to use fooInstance here as well,
    // and no, it is not possible to just pass it in as another parameter
}
于 2012-04-20T16:40:31.410 回答
0

属性只是一个字段,它返回对堆上某个对象的引用(即它的地址)。如果属性不是引用类型,则返回对象的值。

所以,当你做类似的事情时

DoSomething(fooInstance.Bar);

您只需将对象 Bar 的地址传递给方法。

如果 Bar 是引用类型(即类)。想象一下 Mr.Foo 的地址是 Mr.Bar(462 代表印第安纳州马里恩县)。Mrs.CLR 向 Mr.Foo 询问 Mr.Bar 的地址。然后把这个地址告诉需要Mr.Bar地址的人。怎么会有人知道,CLR 向 Foo 询问了 Bar 的地址?他只收到了印第安纳州马里恩县的地址 462

对于值对象(int、double、structs 等),Mr.Foo 有一个很酷的 mp3 曲目,名为 Bar。CLR 夫人创建了该 mp3 曲目的副本并将其发送给某人。怎么会有人知道,他的 mp3 曲目 Bar 是 Mr.Foo 曲目的副本?

所以,如果你想让某人知道 Mr.Foo,你需要将 Mr.Foo 的地址传递给他:

DoSomething(fooInstance);

有了这个地址,有人可以拜访 Mr.Foo 并询问他关于 Mr.Bar 的地址,或者创建他的 mp3 曲目的副本 :)

于 2012-04-20T16:41:13.067 回答