【问题标题】:Loop Statement does not go past 2nd item循环语句不超过第二项
【发布时间】:2012-09-20 12:56:34
【问题描述】:

我仍然是一个初学者开发人员 - 如果我把这个问题弄错了,请原谅我,但我有一个类可以根据另一个公共结构的属性构建一个字符串。当结构被命名时,这曾经可以正常工作,但我想让这个类对任何类型的结构做同样的事情,所以我改为使用对象。这是我用来遍历属性并构造字符串的方法 - 这是在一个名为构造函数的公共类中,然后我从我的其余代码中调用(不创建构造函数的实例)。

    public string MyConstructor(object TheObject)
    {
        string S = "";

        Type t = TheObject.GetType();
        PropertyInfo[] PI = t.GetProperties();

        Constructors Cons = new Constructors();

        foreach (PropertyInfo info in PI)
        {
            S = MyConstructor(S, info, info.GetValue(TheObject, null););
        }

        return S;
    }

我的问题是它不想退出 foreach 循环。当我用

替换它时
        for (int i = 0; i < PI.Count(); i++)
        {
            S = MyConstructor(S, PI[i], PI[i].GetValue(TheObject, null));
        }

并通过调试器运行它 -> 在每个循环之后我进入 0、1、0、1、0、1... MyConstructor 有 2 个重载...上面的一个和另一个带有 (string, PropertyInfo, object) .但即使我将第二种方法的名称更改为 MyPropertyConstructor,也会发生同样的情况。目前,代码是从没有线程的表单中调用的,因此在我看来没有任何其他线程可以干扰。同样对于循环 0 和 1,该方法返回空字符串“”。那么我该如何摆脱这个循环呢?

这是剩下的代码

    public static string MyConstructor(string CompiledString, PropertyInfo PropertyToAdd, object ThisValue)
    {
        string s = "";
        //object ThisValue = PropertyToAdd.GetValue(PropertyToAdd, null);

        //See if there is something to work with
        if(PropertyToAdd != null)
        {
            //Remove items which has been set not to record
            if (PropertyToAdd.GetCustomAttributes(typeof(DontRecord), true).Length > 0)
            {
                if(((DontRecord)PropertyToAdd.GetCustomAttributes(typeof(DontRecord), true)[0]).Record)
                {
                    return CompiledString;
                }
            }

            //see if it is the first time using the compile string
            if (CompiledString != "")
            {
                s += ";";
            }

            //For Testing
            int testint = 0;

            //only record items that where default value is different to their value
            Object[] Attr = PropertyToAdd.GetCustomAttributes(typeof(DefaultValueAttribute), true);

            //see if there is a default value set
            if (Attr.Length > 0)
            {
                //Get Constructorname value
                Object[] constructorname = PropertyToAdd.GetCustomAttributes(typeof(ConstructorName), true);

                if (constructorname.Length > 0)
                {
                    s += ((ConstructorName)constructorname[0]).Name.ToString() + "=";



                    //If value is a string
                    if (PropertyToAdd.PropertyType == typeof(string))
                    {
                        if (Convert.ToString(((DefaultValueAttribute)Attr[0]).Value) != (string)ThisValue) { s += ThisValue; } else { s = ""; }
                    }

                    //Incase value is an int
                    else if (PropertyToAdd.PropertyType == typeof(int) && int.TryParse(ThisValue.ToString(), out testint))
                    {
                        if (Convert.ToInt32(((DefaultValueAttribute)Attr[0]).Value) != (int)ThisValue) { s += Convert.ToString((int)ThisValue); } else { s = ""; }
                    }

                    //Incase value is a bool
                    else if (PropertyToAdd.PropertyType == typeof(bool))
                    {
                        if (Convert.ToBoolean(((DefaultValueAttribute)Attr[0]).Value) != (bool)ThisValue)
                        {
                            if ((bool)ThisValue) { s += "True"; } else { s += "False"; }
                        }
                        else { s = ""; }
                    }
                    else
                    {
                        s = "";
                    }
                }
                else
                {
                    //There is no ConstructorName so therefore cannot create
                    return CompiledString;
                }
            }
            else
            {
                return CompiledString;
            }
        }

        return CompiledString += s;
    }

}

这是最初传递给 MyConstructor 的部分对象类型的公共结构示例

公共结构 ODBCDataString { #region 变量 #region 通用变量 静态字符串_connection =“”; 静态字符串 _saveString = ""; 静态字符串 _unsaveString = ""; #endregion 通用变量

        #region Security Variables
            static string _userID = "";
            static string _password = "";
        #endregion Security Variables

        #region Source Variables
            static string _dsn = "";
            static string _driver = "";
        #endregion Source Variables
    #endregion Variables

    #region Properties
        #region General
            [Browsable(false)]
            public string ConnectionString { get { return _connection; } set { _connection = value; } }

            [Browsable(false)]
            public string SaveString 
            {
                get 
                {
                    Constructors Cons = new Constructors();
                    string MyS = Cons.MyConstructor((object)this);
                    return MyS; 
                } 
            } 

            [Browsable(false)]
            public string UnsaveString 
            { 
                get 
                {
                    Constructors Cons = new Constructors();
                    string MyS = Cons.MyConstructor((object)this);
                    //string MyS = Constructors.MyConstructor((object)this);
                    if (_password != "")
                    {
                        MyS += ";Password=" + _password;
                    }

                    return MyS; 
                } 
            }
        #endregion General

        #region Source
            [DisplayName("DSN")]
            [Description("The DSN to use when connecting to the Data Source")]
            [DefaultValue("")]
            [Category("Source")]
            [ConstructorName("Dsn")]
            public string DSN { get { return _dsn; } set { _dsn = value; } }

...这基本上只是对传递的结构/对象类型的简要概述

【问题讨论】:

  • PI.Count 的值是多少?你期待什么?
  • 你能添加MyConstructor 的其他重载吗?
  • 听起来可能有一些无限递归在进行...让我们看看另一个MyConstructor(),我想知道它是否不会回调这个...
  • 在这种情况下,PI Count 是 6...对于另一个结构,它超过 10,但不确定有多少...基本上我正在尝试即时构建不同的连接字符串...当它只使用 SQL 连接时它工作正常(即每个属性都有一个属性,让我的方法知道是否应该包含它)......在我遇到这个问题之前真的没有那么复杂,并且整个早上都在努力解决
  • 您是否尝试过单步执行代码以查看是否陷入无限递归?

标签: c#


【解决方案1】:
namespace ConsoleApplication1
{
class Program
{
    static void Main(string[] args)
    {
        Test1 t1 = new Test1();
        string result = ObjToString<Test1>(t1);
        Console.WriteLine(result);
        Console.ReadKey();
    }

    public static string ObjToString<T>(T obj)
    {
        if (obj == null)
        {
            throw new Exception("passed in parameter is null");
        }

        StringBuilder sb = new StringBuilder();

        Type t = obj.GetType();
        PropertyInfo[] properties = t.GetProperties();

        foreach (var property in properties)
        {
            sb.Append(property.Name);
            sb.Append(",");
        }

        return sb.ToString();
    }
}

public struct Test1
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
}
}

【讨论】:

    【解决方案2】:

    好的,很抱歉在这里浪费时间,但我发现了问题。正如HOBO建议的那样。我的一个属性也称为相同的方法(实际上它是我在上面的示例中设置的确切类的第二个属性。我评论说一个出来并且代码正在工作。花了一整天之后 - 我觉得自己像个白痴并且浪费了你们所有的时间......非常感谢你们的帮助:)我几乎放弃了一起开发:)

    【讨论】:

    • ps。我认为代码不会因为未设置的 Attribute ConstructorName 而变得诚实...所以我认为如果您只想知道属性的所有属性,则该值也将与返回其余属性?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 2021-04-07
    • 2014-11-25
    相关资源
    最近更新 更多