在类中创建对基本类型字段的引用

时间:2014-11-28 15:40:07

标签: c#

我有一些类有一些原始字段,我想为它们创建一个通用的包装器来访问它们的字段。这个包装器应该以某种方式包含对我的类的字段的引用,以便我可以读/写这些字段的值。我们的想法是为这些类创建一个通用的体系结构,这样我就不必为每个类编写代码。这些类具有包含数字的字段,这些字段将用作访问字段的ID。

这是一些示例代码,可能会对我的要求有所了解。我最终想要的是改变Fancy1类对象中某些字段的值,而不是通过它的包装器访问对象本身。

class Fancy1
{
    public double level1;
    public bool isEnable1;

    public double level2;
    public bool isEnable2;

    public double level3;
}


class Fancy2
{
    public double level4;
    public bool isEnable4;

    public double level6;
    public bool isEnable6;

    public double level7;
}

class FieldWrapper
{
    public int id { get; set; }
    public object level { get; set; }
    public object isEnabled { get; set; }

    public FieldWrapper(int id, object level, object isEnabled)
    {
        this.id = id;
        this.level = level;
        this.isEnabled = isEnabled;
    }
}

class FancyWrapper
{
    private Fancy scn;

    public FancyWrapper(Fancy scn)
    {
        if (!(scn is Fancy))
            throw new ArgumentException(scn.GetType().FullName + " is not a supported type!");

        this.scn = scn;
    }

    private Dictionary<int, FieldWrapper> fieldLut = new Dictionary<int, FieldWrapper>();

    private List<FieldWrapper> _fields { get { return fieldLut.Values.ToList(); } }

    public List<FieldWrapper> fields
    {
        get
        {
            if (_fields.Count == 0)
            {
                foreach (System.Reflection.FieldInfo fieldInfo in scn.GetType().GetFields())
                {
                    if (fieldInfo.FieldType == typeof(double))
                    {
                        int satId = getIdNr(fieldInfo.Name);
                        fieldLut.Add(satId, new FieldWrapper(satId, fieldInfo.GetValue(scn), true));
                    }
                }

                foreach (System.Reflection.FieldInfo fieldInfo in scn.GetType().GetFields())
                {
                    if (fieldInfo.FieldType == typeof(bool))
                    {
                        int satId = getIdNr(fieldInfo.Name);
                        fieldLut[satId].isEnabled = fieldInfo.GetValue(scn);
                    }
                }
            }

            return _fields;
        }
    }

    private int getIdNr(string name)
    {
        System.Text.RegularExpressions.Match m = System.Text.RegularExpressions.Regex.Match(name, @"\d+");
        return Int32.Parse(m.Value);
    }
}


class Program
{
    static void Main(string[] args)
    {
        Fancy1 fancy = new Fancy1();
        fancy.level1 = 1;
        fancy.isEnable1 = true;

        fancy.level2 = 2;
        fancy.isEnable2 = false;

        fancy.level3 = 3;

        FancyWrapper wrapper = new FancyWrapper(fancy);

        wrapper.fields[2].level = 10;

        // fancy.level2 should somehow get the value I set via the wrapper
        Console.WriteLine(fancy.level2);
        Console.ReadLine();

    }
}

编辑:花哨类无法更改,因为它们是界面的一部分!

3 个答案:

答案 0 :(得分:0)

或者您可以投入5分钟学习数据结构。请考虑以下示例:

var levels = new Dictionary<int, bool>
{
    {1, true}, 
    {2, false}
};

if (levels[1])
{
    //will run, because level 1 is true
}
if (levels[2])
{
    //will not run, because level 2 is false
}
if (levels.ContainsKey(3) && levels[3])
{
    //will not run, because dictionary does not contain entry for key 3
}
levels.Add(3, false);
if (levels.ContainsKey(3) && levels[3])
{
    //will not run, because level 3 is false
}
levels[3] = true;
if (levels.ContainsKey(3) && levels[3])
{
    //will run, because level 3 is true
}

答案 1 :(得分:0)

这可能看起来像你想要的,但它确实不是。在任何级别上都非常尴尬。更具体地说,指针通常是&#34; Un-C#-like&#34;并且必须知道这些数字会使得开始分开的课程失败。

仔细考虑你想要完成的事情。如果您在将代码转换为代码时遇到问题,我们将随时为您提供帮助。 :)

答案 2 :(得分:0)

根据您正在处理的Fancy类的数量,您可以为每个公开接口创建一个适配器/外观类。例如:

class Fancy1
{
    public double level1;
    public bool isEnable1;

    public double level2;
    public bool isEnable2;

    public double level3;
}

public class FieldWrapper
{
    private Action<double> _levelSetter;
    private Func<double>   _levelGetter;
    private Action<bool>   _enableSetter;
    private Func<bool>     _enableGetter;

    public double level     { get { return _levelGetter();  } set { _levelSetter(value);  }}
    public bool   isEnabled { get { return _enableGetter(); } set { _enableSetter(value); }}

    internal FieldWrapper(Func<double> levelGetter, Action<double> levelSetter, Func<bool> enableGetter, Action<bool> enableSetter)
    {
        _levelGetter = levelGetter;
        _levelSetter = levelSetter;
        _enableGetter = enableGetter;
        _enableSetter = enableSetter;
    }
}

abstract class FancyWrapper
{
    public FieldWrapper[] Fields { get; protected set; }
}

class Fancy1Wrapper : FancyWrapper
{
    private Fancy1 _fancy1;

    public Fancy1Wrapper(Fancy1 fancy1)
    {
        _fancy1 = fancy1;
        this.Fields = new[] { new FieldWrapper(() => fancy1.level1, level => _fancy1.level1 = level, () => _fancy1.isEnable1, enable => _fancy1.isEnable1 = enable),
                              new FieldWrapper(() => fancy1.level2, level => _fancy1.level2 = level, () => _fancy1.isEnable2, enable => _fancy1.isEnable2 = enable), };
    }
}