View模型中的自定义属性,在TPT继承项目中带有valueinjector

时间:2013-12-16 14:57:30

标签: c# inheritance valueinjecter

我有一个viewmodel,它使用valueinjector从模型中注入值(我也实现了TPT继承)。在此过程中,由于我的一个自定义属性(属性不在模型源中),我不断收到以下错误:

  

对象引用未设置为对象的实例。

我发现valueinjector时不时地继续前往那个属性。如下面的示例所示,自定义属性为“FullName”。

public class EmployeeVm
{
    public EmployeeVm(Employee employee)
    {
        this.InjectFrom<Employee>(employee);
    }

    public EmployeeVm(int id):this(new Context().Employees.Find(id))
    {
    }

    public EmployeeVm()
    {
    }
    public int EmployeeId { get; set; }
    [Display(Name = "First Name")]
    [Required(ErrorMessage = "Pleae enter First Name"), StringLength(50)]
    public string FirstName { get; set; }
    [Display(Name="Middle Name"), StringLength(50)]
    public string MiddleName { get; set; }
    [Display(Name="Last Name"), StringLength(50)]
    [Required(ErrorMessage = "Please enter Last Name")]
    public string LastName { get; set; }

    public string FullName {
        get
        {
            StringBuilder stringBuilder = new StringBuilder();

            stringBuilder.Append("<b>");
            stringBuilder.Append(LastName.ToUpper());
            stringBuilder.Append("</b>");
            if (!string.IsNullOrEmpty(MiddleName))
            {
                stringBuilder.Append(", ");
                stringBuilder.Append(MiddleName);
            }
            stringBuilder.Append(", ");
            stringBuilder.Append(LastName);

            return stringBuilder.ToString();
        }
    }        
}

我想到的唯一解决方案是使valueinjector忽略该属性,以便在设置其他属性之前不尝试获取属性。为此,我尝试在员工模型中编写自定义注入器,如下所示:

[Table("Person")]
public abstract class Person:ConventionInjection
{
    public Person()
    {
        this.PersonAddresses = new List<PersonAddress>();
        this.PersonEmails = new List<PersonEmail>();
        this.PersonPhones = new List<PersonPhone>();
    }

    [Key]
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }



    //public virtual Employee Employee { get; set; }

    protected override bool Match(ConventionInfo c)
    {
      throw new NotImplementedException();
    }



    public List<PersonAddress> PersonAddresses { get; set; }
    public List<PersonEmail> PersonEmails { get; set; }
    public List<PersonPhone> PersonPhones { get; set; }
}

public class Employee:Person
{
    public Employee()
    {
        this.Identifications=new List<Identification>();
        this.BankAccounts=new List<BankAccount>();
    }
    public DateTime? DateOfBirth { get; set; }
    //Other properties are inherited from Person abstract class

    public virtual ICollection<Identification> Identifications { get; set; }
    public virtual ICollection<BankAccount> BankAccounts { get; set; }

    protected override bool Match(ConventionInfo c)
    {
        if (c.TargetProp.Name == "FullName")
        {
            return false;
        }



        var isMatch = (c.SourceProp.Name == "PersonId" && c.TargetProp.Name == "EmployeeId") ||
                      (c.SourceProp.Name == c.TargetProp.Name && c.SourceProp.Type == c.TargetProp.Type);

        return isMatch;

    }
}

尽管如此,我仍然得到了同样的上述错误。

我还发现了另一种解决方案,它会覆盖LoopValueInjection的UseSourceProp方法。

http://valueinjecter.codeplex.com/discussions/234706

但是,在我的场景中它不是那么容易,因为我已经在我的基类和派生类中继承了一个类。并且要实现自定义valueinjector也是不可能的,因为您可以从EmployeeVm viewmodel中看到它。

this.InjectFrom<Employee>(employee);

如果有人能帮我解决这个问题,或者还有其他解决方案,我将不胜感激。

另外,观众的感谢。

1 个答案:

答案 0 :(得分:3)

试试这个:

在EmployeeVm的构造函数中:

public EmployeeVm(Employee employee)
{
    this.InjectFrom<Employee>(employee);

    stringBuilder = new StringBuilder();
    stringBuilder.Append("<b>");
    stringBuilder.Append(LastName.ToUpper());
     stringBuilder.Append("</b>");
     if (!string.IsNullOrEmpty(MiddleName))
     {
           stringBuilder.Append(", ");
           stringBuilder.Append(MiddleName);
     }
      stringBuilder.Append(", ");
     stringBuilder.Append(FirstName);
     this.FullName = stringBuilder.ToString();
}

将FullName属性转换为auto属性:

public string FullName { get; set; }

另外,将Employee中的覆盖方法更改为:

protected override bool Match(ConventionInfo c)
{
    var isMatch = (c.SourceProp.Name == "PersonId" && c.TargetProp.Name == "EmployeeId") ||(c.SourceProp.Name == c.TargetProp.Name && c.SourceProp.Type == c.TargetProp.Type);

      return isMatch;

}

您不需要覆盖匹配属性或LoopValueInjector的useSourceProp。匹配用于返回source和target属性是否匹配,useSourceProp用于忽略SourceProperty,以便它不映射到target属性。

在您的方案中,source属性没有Full Name属性,关于匹配,您不必告诉它名称与之不匹配,不会映射属性。

错误是由于

LastName.ToUpper()

在分配值之前,尝试将LastName属性转换为upper。因此,如果在valueinjector设置值之后在构造函数中设置值,则应该解决问题。