比较两个对象的最佳方法。测验

时间:2014-12-30 13:09:04

标签: c# asp.net-mvc reflection

我为一些朋友做了一个新的一年的测验。测验本身已经完成并正常工作我只是认为一旦发布后自动更正答案会很酷。

问题是将发布的对象与具有所有正确答案的对象(反射)进行比较的最佳方法是什么?必须有一个光滑的方式去做,并避免有很多if。

public class QuizModel
{
    public string Name { get; set; }
    public string Quiz1 { get; set; }
    public string Quiz2 { get; set; }
    public string Quiz3 { get; set; }
    etc..
}

你不必给我写任何代码。我只是想要了解最好(最重要的是最酷)的方法:)

5 个答案:

答案 0 :(得分:1)

您不需要使用反射来比较值,不是:)

如果所有值都封装在模型中,那么比较逻辑也应如此。一种简单的方法可能是覆盖.Equals()。像这样:

public override bool Equals(object obj)
{
    if (obj == null)
        return false;
    if (!(obj is QuizModel))
        return false;
    var quiz = obj as QuizModel;
    return
        quiz.Name.Equals(this.Name) &&
        quiz.Quiz1.Equals(this.Quiz1) &&
        // etc.
}

当然,这很容易。 真正的挑战将是字符串比较逻辑。字符串听起来像自由文本输入。因此,如果其中一个答案是"圣诞节"那么你如何处理像#34;圣诞节那样的投入"或者"圣诞节"或" 12月25日"等等?这取决于您的业务逻辑。但是"的实际逻辑是这两个对象相等"很简单。

从语义上讲,您可以选择不为此目的覆盖.Equals()。我可以看到一个很好的论据反对它,声称对象是不同的,但只是包含相同的值。 (一个很好的现实世界的例子是同卵双胞胎。)因此,您可以选择实施其他内容,例如IEquatable或仅使用.IsEqualTo(QuizModel quiz)等自定义方法。但其中的逻辑无论如何都是相同的。

答案 1 :(得分:1)

至于你的解释,这个类的实现应该是答案列表(或字典,或数组等):

public class QuizModel
{
    public string Name { get; set; }
    public List<string> Quizs { get; set; }
}

然后,检查所有答案是否相同:

public bool AreEqual(model1, model2){

  for(var i = 0; i < Math.Min(model1.Quizs.Count, model2.Quizs.Count); ++i)
    if(model1.Quizs[i] != model2.Quizs[i])
      return false;

  return true;
}

以类似的方式,您可以获得相同的答案数量。

答案 2 :(得分:1)

我为您的问题提供了两个解决方案。我想你想给你的朋友分数(我会这样做)。如果是这样,这里有一个解决方案可以为您提供答案的分数,我假设每个测验具有相同的值,并且您对所有测验都有正确的答案。首先你可以尝试通过反射比较quizes的所有值,并返回总数(假设你的quizes具有相同的值。那么如果你想在下面更灵活,我建议你一个可能的解决方案,当quizes可能有不同的值(评分)。

1)  公共类QuizModel     {         public string Name {get;组; }         public string Quiz1 {get;组; }         public string Quiz2 {get;组; }         public string Quiz3 {get;组; }     }

public class QuizComparer
{

    public QuizComparer(QuizModel correctOne, IComparer<string> comparer, int quizValue = 1)
    {
        this.CorrectOne = correctOne;
        this.Comparer = comparer;
        this.QuizValue = quizValue;
    }
    public int Compare(QuizModel toCompareOne)
    {
        Type type = toCompareOne.GetType();
        var propertiesInfo = type.GetProperties();

        int result = 0;

        foreach (var propertyInfo in propertiesInfo)
        {
            if (propertyInfo.CanRead)
            {
                var toCompareOnePropertyValue = type.GetProperty(propertyInfo.Name).GetValue(toCompareOne).ToString();
                var correctOnePropertyValue = type.GetProperty(propertyInfo.Name).GetValue(this.CorrectOne).ToString();

                if (Comparer.Compare(toCompareOnePropertyValue, correctOnePropertyValue) == 0)//equals
                {
                    result += QuizValue;
                }

            }
        }

        return result;
    }

    public QuizModel CorrectOne { get; set; }

    public IComparer<string> Comparer { get; set; }


    public int QuizValue { get; set; }
}

2)其次,如果你想给你的quizes个人分数,你会发现这非常有帮助:

public class QuizModel
{
    public string Name { get; set; }
    [QuizValue(value: 1)]
    public string Quiz1 { get; set; }

    [QuizValue(value: 2)]
    public string Quiz2 { get; set; }

    [QuizValue(value: 3)]
    public string Quiz3 { get; set; }
}

public class QuizComparer
{

    public QuizComparer(QuizModel correctOne, IComparer<string> comparer, int quizValue = 1)
    {
        this.CorrectOne = correctOne;
        this.Comparer = comparer;
        this.QuizDefaultValue = quizValue;
    }
    public int Compare(QuizModel toCompareOne)
    {
        Type type = toCompareOne.GetType();
        var propertiesInfo = type.GetProperties();

        int result = 0;

        foreach (var propertyInfo in propertiesInfo)
        {
            if (propertyInfo.CanRead && propertyInfo.Name != "Name")
            {
                var toCompareOnePropertyValue = type.GetProperty(propertyInfo.Name).GetValue(toCompareOne).ToString();
                var correctOnePropertyValue = type.GetProperty(propertyInfo.Name).GetValue(this.CorrectOne).ToString();

                int value = GetQuizValue(propertyInfo);
                if (Comparer.Compare(toCompareOnePropertyValue, correctOnePropertyValue) == 0)//equals
                {
                    result += value;
                }

            }
        }

        return result;
    }

    private int GetQuizValue(PropertyInfo propertyInfo)
    {
        var attributes = propertyInfo.GetCustomAttributes(typeof(QuizValue), false);

        int value = this.QuizDefaultValue;
        if (attributes != null && attributes.Count() > 0)
        {
            var quizValueAttribute = attributes[0];
            if (quizValueAttribute is QuizValue)
            {
                var quizValue = quizValueAttribute as QuizValue;
                value = quizValue.Value;
            }

        }
        return value;
    }

    public QuizModel CorrectOne { get; set; }

    public IComparer<string> Comparer { get; set; }


    public int QuizDefaultValue { get; set; }
}

[System.AttributeUsage(System.AttributeTargets.Property)]
public class QuizValue : System.Attribute
{

    public QuizValue(int value = 1)
    {
        this.Value = value;
    }

    public int Value
    {
        get;
        set;
    }
}

答案 3 :(得分:0)

请尝试如下,这可能会让您得到您的想法

它会始终将 Quiz2 Quiz1 值进行比较。

public string Quiz1 {get; set;}

[CompareAttribute("Quiz1", ErrorMessage = "Quiz2 is mismatch with Quiz1")]
public string Quiz2 { get; set; }

答案 4 :(得分:0)

这只会给你错误的答案:

var quiz = new QuizModel() { Name = "Quiz 1", Quiz1 = "Correct answer", Quiz2 = "Correct answer", Quiz3 = "Correct answer"  };
var correctQuiz = new QuizModel() { Name = "Quiz 1",  Quiz1 = "Correct answer", Quiz2 = "Wrong answer", Quiz3 = "Wrong answer 2" };

Func<QuizModel, List<string>> getListOfAnswers = (currentquiz) => 
(
    from property
    in typeof(QuizModel).GetProperties()
    select property.Name + " " + property.GetValue(currentquiz)
).ToList();

var answers = getListOfAnswers(quiz);
var correctAnswers = getListOfAnswers(correctQuiz); 

var wrongAnswers = correctAnswers.Except(answers);  

输出:

  

测验2错误回答

     

测验3错误回答2

这个解决方案一次使用Reflection,LINQ和Anonymous功能,所以很酷:)