C# 是否可以按名称访问属性(这是一个变量)?
抱歉,如果有人问我并回答了这个问题,我已经搜索过了,但我想我不知道找到答案的词汇。研究反思,但这似乎不是答案?我显然是个新手。我正在尝试/为新战地科技游戏的mod做一些小贡献 我有这本C# 是否可以按名称访问属性(这是一个变量)?,c#,C#,抱歉,如果有人问我并回答了这个问题,我已经搜索过了,但我想我不知道找到答案的词汇。研究反思,但这似乎不是答案?我显然是个新手。我正在尝试/为新战地科技游戏的mod做一些小贡献 我有这本字典,想用它的键来设置属性,如下面的foreach所示。我不知道这是在编译时还是在运行时,我猜是在编译时 我把“肢体”作为伪代码放进去,以说明我想象它是如何工作的。属性mechDef.Head是类型为LocationLoadoutDef的对象,其属性CurrentInternalStructure为float 希望
字典
,想用它的键来设置属性,如下面的foreach
所示。我不知道这是在编译时还是在运行时,我猜是在编译时
我把“肢体”作为伪代码放进去,以说明我想象它是如何工作的。属性mechDef.Head
是类型为LocationLoadoutDef
的对象,其属性CurrentInternalStructure
为float
希望这有意义
非常感谢您的帮助
public class Settings {
public readonly Dictionary<string, bool> LimbRepair = new Dictionary<string, bool> {
{ "Head", false },
{ "LeftArm", false },
{ "RightArm", false },
{ "CenterTorso", false },
{ "LeftTorso", false },
{ "RightTorso", false },
{ "LeftLeg", false },
{ "RightLeg", false },
};
}
MechDef mechDef = new MechDef
(__instance.DataManager.MechDefs.Get(id), __instance.GenerateSimGameUID());
foreach (string limb in settings.LimbRepair.Keys) {
if (!settings.LimbRepair[limb]) {
mechDef.*limb*.CurrentInternalStructure = Math.Max
(1f, mechDef.*limb*.CurrentInternalStructure * (float)rng.NextDouble());
}
公共类设置{
公共只读词典LimbRepair=新词典{
{“Head”,false},
{“左臂”,false},
{“右臂”,假},
{“中心躯干”,假},
{“LeftTorson”,false},
{“rightstorson”,false},
{“LeftLeg”,false},
{“RightLeg”,false},
};
}
MechDef MechDef=新MechDef
(_instance.DataManager.MechDefs.Get(id),_instance.GenerateSimGameUID());
foreach(settings.LimbRepair.Keys中的字符串肢体){
如果(!settings.LimbRepair[limb]){
mechDef.*肢体*.CurrentInternalStructure=Math.Max
(1f,mechDef.*肢体*.CurrentInternalStructure*(float)rng.NextDouble());
}
您可以创建一个DynamicObject来创建自己的动态字典
假设您希望为访问提供替代语法
字典中的值,这样就不用写了
示例字典[“文本”]=“示例文本”,您可以编写
sampleDictionary.Text=“示例文本”
这是上面同一篇MSDN文章中的示例:
public class DynamicDictionary : DynamicObject
{
// The inner dictionary
Dictionary<string, object> dictionary = new Dictionary<string, object>();
public int Count
{
get { return dictionary.Count; }
}
// If you try to get a value of a property not defined
// in the class, this method is called.
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
// Converting the property name to lowercase so
// that property names become case-insensitive.
string name = binder.Name.ToLower();
// If the property name is found in a dictionary, set the result parameter
// to the property value and return true. Otherwise, return false.
return dictionary.TryGetValue(name, out result);
}
// If you try to set a value of a property that is not
// defined in the class, this method is called.
public override bool TrySetMember(SetMemberBinder binder, object value)
{
// Converting the property name to lowercase so that
// property names become case-insensitive.
dictionary[binder.Name.ToLower()] = value;
// You can always add a value to a dictionary, so this method always returns true.
return true;
}
}
您可以创建DynamicObject来创建自己的动态字典 假设您希望为访问提供替代语法 字典中的值,这样就不用写了 示例字典[“文本”]=“示例文本”,您可以编写 sampleDictionary.Text=“示例文本” 这是上面同一篇MSDN文章中的示例:
public class DynamicDictionary : DynamicObject
{
// The inner dictionary
Dictionary<string, object> dictionary = new Dictionary<string, object>();
public int Count
{
get { return dictionary.Count; }
}
// If you try to get a value of a property not defined
// in the class, this method is called.
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
// Converting the property name to lowercase so
// that property names become case-insensitive.
string name = binder.Name.ToLower();
// If the property name is found in a dictionary, set the result parameter
// to the property value and return true. Otherwise, return false.
return dictionary.TryGetValue(name, out result);
}
// If you try to set a value of a property that is not
// defined in the class, this method is called.
public override bool TrySetMember(SetMemberBinder binder, object value)
{
// Converting the property name to lowercase so that
// property names become case-insensitive.
dictionary[binder.Name.ToLower()] = value;
// You can always add a value to a dictionary, so this method always returns true.
return true;
}
}
反射是获取它的一种方法。实际上,它完美地回答了这个问题。不过,我会重新构造您的数据,使
mechDef
对象成为另一个字典,但如果您必须按照问题的要求保留它,这将起作用:
void Main()
{
Dictionary<string, bool> limbRepair = new Dictionary<string, bool>
{
{ "Head", false },
{ "LeftArm", false },
{ "RightArm", false },
// Etc.
};
MechDefinition mechDef = new MechDefinition();
List<Limb> limbs = new List<Limb>();
foreach (KeyValuePair<string, bool> limbsToRepair in limbRepair.Where(x => !x.Value))
{
Limb limb = mechDef.GetPropValue<Limb>(limbsToRepair.Key);
limb.CurrentInternalStructure = 9001;
}
}
public class MechDefinition
{
public MechDefinition()
{
Head = new Limb
{
Id = Guid.NewGuid(),
DateAdded = DateTime.Parse("2018-01-01"),
Name = "Main Head",
CurrentInternalStructure = 8675309
};
}
public Guid Id { get; set; }
public string Name { get; set; }
public int CurrentInternalStructure { get; set; }
public Limb Head { get; set; } = new Limb();
public Limb LeftArm { get; set; } = new Limb();
public Limb RightArm { get; set; } = new Limb();
// etc...
}
public class Limb
{
public Guid Id { get; set; }
public string Name { get; set; }
public DateTime DateAdded { get; set; }
public int CurrentInternalStructure { get; set; }
public bool IsDisabled { get; set; }
}
public static class ReflectionHelpers
{
public static object GetPropValue(this object obj, string name)
{
foreach (string part in name.Split('.'))
{
if (obj == null) { return null; }
Type type = obj.GetType();
PropertyInfo info = type.GetProperty(part);
if (info == null) { return null; }
obj = info.GetValue(obj, null);
}
return obj;
}
public static T GetPropValue<T>(this object obj, string name)
{
object retval = GetPropValue(obj, name);
if (retval == null) { return default(T); }
// throws InvalidCastException if types are incompatible
return (T)retval;
}
}
void Main()
{
Dictionary limbRepair=新字典
{
{“Head”,false},
{“左臂”,false},
{“右臂”,假},
//等等。
};
MechDefinition mechDef=新的MechDefinition();
列表肢体=新列表();
foreach(limbRepair.Where(x=>!x.Value))中的KeyValuePair limbsToRepair
{
肢体肢体=mechDef.GetPropValue(limbsToRepair.Key);
limb.CurrentInternalStructure=9001;
}
}
公共类定义
{
公共定义()
{
头部=新肢体
{
Id=Guid.NewGuid(),
DateAdded=DateTime.Parse(“2018-01-01”),
Name=“主要负责人”,
CurrentInternalStructure=8675309
};
}
公共Guid Id{get;set;}
公共字符串名称{get;set;}
公共int CurrentInternalStructure{get;set;}
公共肢体头部{get;set;}=new Limb();
公共肢体左臂{get;set;}=新肢体();
公共肢体右臂{get;set;}=新肢体();
//等等。。。
}
公共类肢体
{
公共Guid Id{get;set;}
公共字符串名称{get;set;}
public DateTime DateAdded{get;set;}
公共int CurrentInternalStructure{get;set;}
公共布尔被禁用{get;set;}
}
公共静态类ReflectionHelpers
{
公共静态对象GetPropValue(此对象对象,字符串名称)
{
foreach(name.Split('.')中的字符串部分)
{
如果(obj==null){返回null;}
Type Type=obj.GetType();
PropertyInfo=type.GetProperty(部分);
如果(info==null){returnnull;}
obj=info.GetValue(obj,空);
}
返回obj;
}
公共静态T GetPropValue(此对象对象对象,字符串名称)
{
object retval=GetPropValue(obj,name);
如果(retval==null){返回默认值(T);}
//如果类型不兼容,则引发InvalidCastException
返回(T)返回;
}
}
请注意,反射是一项成本非常高的操作。如果您处理的是大型数据集,它的效率将非常低。请查看性能概述
同样在代码方面,我更喜欢远离动态和反射。当你需要访问属性属性时,反射有它的好处,如果你没有强类型对象,动态是很好的。尽管如此,C#是一种强类型语言,应该尽可能地被视为强类型语言。通过重组你的
mechDef
作为一个字典
对象或类似的东西,你会有一个更高效的应用程序。反射是一种获得它的方法。实际上,它完美地回答了这个问题。但是,我会重新构造你的数据,使mechDef
对象是另一个字典,但是如果你必须按照你的问题保留它,这将起作用:
void Main()
{
Dictionary<string, bool> limbRepair = new Dictionary<string, bool>
{
{ "Head", false },
{ "LeftArm", false },
{ "RightArm", false },
// Etc.
};
MechDefinition mechDef = new MechDefinition();
List<Limb> limbs = new List<Limb>();
foreach (KeyValuePair<string, bool> limbsToRepair in limbRepair.Where(x => !x.Value))
{
Limb limb = mechDef.GetPropValue<Limb>(limbsToRepair.Key);
limb.CurrentInternalStructure = 9001;
}
}
public class MechDefinition
{
public MechDefinition()
{
Head = new Limb
{
Id = Guid.NewGuid(),
DateAdded = DateTime.Parse("2018-01-01"),
Name = "Main Head",
CurrentInternalStructure = 8675309
};
}
public Guid Id { get; set; }
public string Name { get; set; }
public int CurrentInternalStructure { get; set; }
public Limb Head { get; set; } = new Limb();
public Limb LeftArm { get; set; } = new Limb();
public Limb RightArm { get; set; } = new Limb();
// etc...
}
public class Limb
{
public Guid Id { get; set; }
public string Name { get; set; }
public DateTime DateAdded { get; set; }
public int CurrentInternalStructure { get; set; }
public bool IsDisabled { get; set; }
}
public static class ReflectionHelpers
{
public static object GetPropValue(this object obj, string name)
{
foreach (string part in name.Split('.'))
{
if (obj == null) { return null; }
Type type = obj.GetType();
PropertyInfo info = type.GetProperty(part);
if (info == null) { return null; }
obj = info.GetValue(obj, null);
}
return obj;
}
public static T GetPropValue<T>(this object obj, string name)
{
object retval = GetPropValue(obj, name);
if (retval == null) { return default(T); }
// throws InvalidCastException if types are incompatible
return (T)retval;
}
}
void Main()
{
Dictionary limbRepair=新字典
{
{“Head”,false},
{“左臂”,false},
{“右臂”,假},
//等等。
};
MechDefinition mechDef=新的MechDefinition();
列表肢体=新列表();
foreach(limbRepair.Where(x=>!x.Value))中的KeyValuePair limbsToRepair
{
肢体肢体=mechDef.GetPropValue(limbsToRepair.Key);
limb.CurrentInternalStructure=9001;
}
}
公共类定义
{
公共定义()
{
头部=新肢体
{
var updates = settings.LimbRepair.Where(pair => pair.Value.Active == false)
.Select(pair => pair.Value);
foreach (var repair in updates)
{
repair.Update();
}
class LocationLoadoutDef
{
public LocationLoadoutDef()
{
Head = new Prop();
LeftArm = new Prop();
RightArm = new Prop();
CenterTorso = new Prop();
LeftTorso = new Prop();
RightTorso = new Prop();
LeftLeg = new Prop();
RightLeg = new Prop();
}
public Prop Head { get; set; }
public Prop LeftArm { get; set; }
public Prop RightArm { get; set; }
public Prop CenterTorso { get; set; }
public Prop LeftTorso { get; set; }
public Prop RightTorso { get; set; }
public Prop LeftLeg { get; set; }
public Prop RightLeg { get; set; }
...
}
class Prop
{
public float CurrentInternalStructure { get; set; }
...
}
// your instance of LocationLoadoutDef
var mechDef = new LocationLoadoutDef();
//For reflection you need obtain the type
Type mechType = mechDef.GetType();
// loop your Dictionary
foreach (string limb in LimbRepair.Keys)
{
// If the property is false in the dictionary and the type has a property with that name
if (!LimbRepair[limb] && mechType.GetProperties().Any(p => p.Name == limb))
{
// Obtain the instance of the property
var property = mechType.GetProperty(limb).GetValue(mechDef) ;
// Get the property type
Type propertyType = property.GetType();
// If the property has a property CurrentInternalStructure
if (propertyType.GetProperties().Any(p => p.Name == "CurrentInternalStructure"))
{
// Obtain the current value for CurrentInternalStructure
var currentValue = propertyType.GetProperty("CurrentInternalStructure").GetValue(property);
// calculate the new value (I don't know what is rng)
var newValue = 1f ; //Math.Max(1f, (float)currentValue * (float)rng.NextDouble());
// set de value in the property
propertyType.GetProperty("CurrentInternalStructure").SetValue(property, newValue);
}
}
}
class PropertyWrapper<T>
{
private readonly Func<T> _getter;
private readonly Action<T> _setter;
public PropertyWrapper(Func<T> getter, Action<T> setter)
{
_getter = getter;
_setter = setter;
}
public T Value
{
get
{
return _getter();
}
set
{
_setter(value);
}
}
}
class MechDef
{
public Limb Head { get; set; }
public Limb LeftArm { get; set; }
public Limb RightArm { get; set; }
public Limb LeftTorso { get; set; }
public Limb RightTorso { get; set; }
public Limb CenterTorso { get; set; }
public Limb RightLeg { get; set; }
public Limb LeftLeg { get; set; }
private readonly Dictionary<string, PropertyWrapper<Limb>> Properties;
public MechDef()
{
Properties = new Dictionary<string, PropertyWrapper<Limb>>
{
{"Head", new PropertyWrapper<Limb>( () => Head, v => Head = v ) },
{"LeftArm", new PropertyWrapper<Limb>( () => LeftArm, v => LeftArm = v ) },
{"RightArm", new PropertyWrapper<Limb>( () => RightArm, v => RightArm = v ) },
{"CenterTorso",new PropertyWrapper<Limb>( () => CenterTorso, v => CenterTorso = v )},
{"RightTorso", new PropertyWrapper<Limb>( () => RightTorso, v => RightTorso = v ) },
{"LeftTorso", new PropertyWrapper<Limb>( () => LeftTorso, v => LeftTorso = v ) },
{"RightLeg", new PropertyWrapper<Limb>( () => RightLeg, v => RightLeg = v ) },
{"LeftLeg", new PropertyWrapper<Limb>( () => LeftLeg, v => LeftLeg = v ) }
};
foreach (var property in Properties.Values) property.Value = new Limb();
}
public Limb this[string name]
{
get
{
return Properties[name].Value;
}
set
{
Properties[name].Value = value;
}
}
}
foreach (var pair in settings.LimbRepair)
{
if (pair.Value != false) continue;
var limb = mechDef[pair.Key];
limb.CurrentInternalStructure = Math.Max
(
1.0F,
limb.CurrentInternalStructure * (float)rng.NextDouble()
);
}