Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否可以按名称访问属性(这是一个变量)?_C# - Fatal编程技术网

C# 是否可以按名称访问属性(这是一个变量)?

C# 是否可以按名称访问属性(这是一个变量)?,c#,C#,抱歉,如果有人问我并回答了这个问题,我已经搜索过了,但我想我不知道找到答案的词汇。研究反思,但这似乎不是答案?我显然是个新手。我正在尝试/为新战地科技游戏的mod做一些小贡献 我有这本字典,想用它的键来设置属性,如下面的foreach所示。我不知道这是在编译时还是在运行时,我猜是在编译时 我把“肢体”作为伪代码放进去,以说明我想象它是如何工作的。属性mechDef.Head是类型为LocationLoadoutDef的对象,其属性CurrentInternalStructure为float 希望

抱歉,如果有人问我并回答了这个问题,我已经搜索过了,但我想我不知道找到答案的词汇。研究反思,但这似乎不是答案?我显然是个新手。我正在尝试/为新战地科技游戏的mod做一些小贡献

我有这本
字典
,想用它的键来设置属性,如下面的
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()
        );
}