سؤال

I am having a viewmodel which uses valueinjector to inject the values from models (I have also implemented TPT inheritance). During this process, due to one of my custom property (Property that is not in the model source), I keep on getting the following error:

Object reference not set to an instance of an object.

I found that valueinjector keeps on going to that property every now and then. As shown in the example below the custom property is "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();
        }
    }        
}

The only solution that crossed my mind is to make valueinjector ignore that property so that it does not try to get the property before setting other properties. For this I tried to write custom injector in the employee model as follows:

[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;

    }
}

In-spite of this, I kept on getting the same above mentioned error.

I also found another solution which says to override UseSourceProp method of LoopValueInjection.

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

But, its not so easy in my scenario as I already have inherited one class in my base class as well as derived class. And to implement the custom valueinjector also its not possible as you can see it from EmployeeVm viewmodel.

this.InjectFrom<Employee>(employee);

I would appreciate if someone could help me with this implementation or if there is any other solution.

Also, thanx for the viewers.

هل كانت مفيدة؟

المحلول

Try this:

In the constructor of 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();
}

Convert FullName property to auto property:

public string FullName { get; set; }

Also, change the override method in the Employee to:

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;

}

You don’t need to override the match property or useSourceProp of LoopValueInjector. The match is for returning whether the source and target property matches or not and useSourceProp is for ignoring the SourceProperty so that it does not map to the target property.

In your scenario, the source property doesn’t have Full Name property and regarding match you don’t have to tell as if the name doesn’t match it won’t map the property.

The error was due to

LastName.ToUpper()

Which tried to convert the LastName property to upper before assigning the value. So, if you set the value in the constructor after valueinjector sets the value, the problem should be solved.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top