2

valueinjector を使用してモデルから値を注入するビューモデルを使用しています (TPT 継承も実装しています)。このプロセス中に、カスタム プロパティ (モデル ソースにないプロパティ) の 1 つが原因で、次のエラーが発生し続けます。

オブジェクト参照がオブジェクト インスタンスに設定されていません。

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

しかし、基本クラスと派生クラスで既に 1 つのクラスを継承しているため、私のシナリオではそれほど簡単ではありません。また、EmployeeVm ビューモデルからわかるように、カスタム valueinjector を実装することもできません。

this.InjectFrom<Employee>(employee);

誰かがこの実装を手伝ってくれたり、他の解決策があれば幸いです。

また、視聴者に感謝します。

4

1 に答える 1

3

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.

于 2013-12-17T03:52:49.017 に答える