3

我目前正在研究 nHibernate,并且对动态访问持久对象中的属性有疑问。

我有以下课程Domain

public class Locations {
    public virtual string CountryCode;
    public virtual string CountryName;
}

现在,假设我有一个 Locations 对象的引用,我有什么办法可以做这样的事情吗?

Locations myCountry = new LocationsRepository().GetByCountryCode("US");
myCountry.Set("CountryName", "U.S.A.");

而不是必须这样做:

myCountry.CountryName = "U.S.A."

没有反思?

4

5 回答 5

1

如果您避免反射的目标是提高性能,那么一个简单的解决方案是使用以下所有属性对功能进行硬编码:

public class Locations {
    public virtual string CountryCode;
    public virtual string CountryName;

    public void Set(string propertyName, string value) {
        if (propertyName == "CountryCode") this.CountryCode = value;
        else if (propertyName == "CountryName") this.CountryName = value;
        else throw new ArgumentException("Unrecognized property '" + propertyName + "'");
    }
}

通过使用T4 模板Set以编程方式为所有域类生成方法,您可以轻松地使这种方法变得可行。事实上,我们在自己的代码库中做了类似的事情,使用 T4 模板生成适配器和序列化程序,以避免在运行时反射成本,同时在编译时获得反射代码生成的灵活性。

于 2012-05-15T12:34:10.603 回答
1

我知道你说“没有反射”,但反射并不全是坏的(当然不像人们想象的那么慢),所以值得一提的是这里的反射解决方案:

using System.Reflection;

typeof(Locations).GetProperty("CountryName").SetValue(myCountry, "U.S.A.", null);

,完成。

于 2012-05-15T12:46:33.533 回答
1

您正在寻找的东西既像具有属性的普通对象,又像字典一样。如果您使用的是 .NET4,您可能会看看ExpandoObject就是这样。

于 2012-05-15T13:04:31.910 回答
1

我讨厌在 StackOverflow 上回答我自己的问题,我感谢每个人的回答,但他们都没有真正为我这样做。经过一番研究,我发现最新版本的 NHibernate 提供了动态模型

虽然很方便,但它们的实验性质让我对在生产中使用它们有点怀疑,所以我做了更多的研究。我发现 SE 自己的 Marc Gravell 继承了他的 HyperDescriptor 库,称为Fastmember。它利用了 DLR 提供的速度增益,并将其与更简单的反射语法结合在一起。我在我的基实体类中将 FastMember 访问实现为简单的 GetValue 和 SetValue 方法,并且我在做生意。

于 2012-06-10T22:02:54.663 回答
0

没有反思,这可能是一个想法:

public class Locations 
{
  private Dictionary<string, object> _values;
  public Locations() 
  {
    _values = new Dictionary<string, object>();
  }
  public void Set(string propertyName, object value)
  {
     if(!_values.ContainsKey(propertyName))
        _values.Add(propertyName, value);
     else
        _values[propertyName] = value;
  }
  public object Get(string propertyName)
  {
     return _values.ContainsKey(propertyName) ? _values[propertyName] : null;
  }

  public string CountryCode
  {
     get{ return Get("CountryCode"); }
     set{ Set("CountryCode", value); }
  }
}

通过这种方式,您无需反射即可访问属性并使用单一方法更改它们。我没有测试过这段代码,但我希望这就是你所说的“不能直接访问该属性”的意思。

于 2012-05-15T12:33:39.640 回答