我目前正在削减对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."
没有反思?
答案 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); }
}
}
通过这种方式,您可以在不反射的情况下访问该属性,并使用单个方法更改它们。我没有测试过这段代码,但我希望这是你所说的“不能直接访问该属性。”