在NHibernate中动态引用属性?

时间:2012-05-15 12:26:16

标签: c# nhibernate reflection

我目前正在削减对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."

没有反思?

5 个答案:

答案 0 :(得分: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 templates以编程方式为所有域类生成Set方法,您可以轻松地使此方法成为可能。实际上,我们在自己的代码库中执行类似的操作,使用T4模板生成适配器和序列化程序,以避免在运行时反射的成本,同时在编译时获得代码生成的反射灵活性。 / p>

答案 1 :(得分:1)

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

using System.Reflection;

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

poof ,已完成。

答案 2 :(得分:1)

您正在寻找的行为类似于具有属性的普通对象,同时也喜欢字典。如果您使用的是.NET4,那么您可以查看ExpandoObject就是这样。

答案 3 :(得分:1)

我讨厌在StackOverflow上回答我自己的问题,我很感激大家的回答,但他们都没有真正为我做过。经过一些研究后,我发现NHibernate的最新版本提供了dynamic models

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

答案 4 :(得分: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); }
  }
}

通过这种方式,您可以在不反射的情况下访问该属性,并使用单个方法更改它们。我没有测试过这段代码,但我希望这是你所说的“不能直接访问该属性。”