سؤال

I need to extend the Omu.ValueInjecter to perform a check before a property assignment is made. Given the code example below, assignment of prop A should only occur if SetA is true. I suspect LoopValueInjection is not the right base class here, but could someone correct the code below so that I can check SetA during the injection process?

var source = new Source() { A = 3 };
var dest = new Dest();
dest.InjectFrom<MyInjector>(source);

public class Source
{
    public int A { get; set; }
    public bool SetA { get; set; }
}
public class Dest
{
    public int A { get; set; }
}

public class MyInjector : LoopValueInjection // or some other base class!
{
    protected override bool AllowSetValue(object value)
    {
        // check SetA!!
        //return base.AllowSetValue(value);
    }
}
هل كانت مفيدة؟

المحلول

Ok, I have it working now. Below is the correct code. I missed the UseSourceProp overload which served my purposes exactly.

The problem I was trying to solve was with MVC after a view model is posted to an action, you must copy the view model data into the data model. When the data model is initialized there could be certain defaults that are set. And when the view model was injected, those defaults would be overwritten. It would be correct to overwrite those if the view model properties had been set, but I had default values being overwritten by view model values that had not been set from a post operation.

The solution was to put a flag in the view model that would indicate whether a property had been set are not. And the setter for each property I simply updated a common list string object in the base class.

In the code below in the UseSourceProp method, you can see that if the property name being processed does not exist in SetProperties, then the method returns false and the property is not set.

var source = new Source() { A = 3 };
var dest = new Dest();
dest.InjectFrom<MyInjector>(source);

public class Source
{
    public int A { get; set; }
    public bool SetA { get; set; }
}
public class Dest
{
    public int A { get; set; }
}

public class MyInjector : LoopValueInjection // or some other base class!
{
    protected override void Inject(object source, object target)
    {
        if (source is BaseEntityViewModel) _baseEntityViewModel = (BaseEntityViewModel)source;
        base.Inject(source, target);
    }
    protected override bool UseSourceProp(string sourcePropName)
    {
        if (_baseEntityViewModel is BaseEntityViewModel)
            return _baseEntityViewModel.SetProperties.Contains(sourcePropName);
        else
            return base.UseSourceProp(sourcePropName);
    }
}

نصائح أخرى

I think overridding the SetValue method might be what you need. This is a slight modification of the docs from here: http://valueinjecter.codeplex.com/wikipage?title=Getting%20started&referringTitle=Documentation and http://valueinjecter.codeplex.com/discussions/355101

public class MyInjector : LoopValueInjection
{       
    //by default is return sourcePropertyValue; override to change behaviour 
    protected override object SetValue(ConventionInfo c)
    {
        // this is just a sample, but you could write anything here
        return new Dest 
        { 
            //Check if source value is true and only then set property

            if(c.SourceProp.Name == "SetA")
            {
              var setASourceVal = c.TargetProp.Value As bool;
              if(setASourceVal)
              {
                A = sourcePropertyValue;
              }
            }
        }
    }
}

depends which injection your using, with ConventionInjection you have the value in the Match method https://valueinjecter.codeplex.com/wikipage?title=step%20by%20step%20explanation&referringTitle=Home

for the LoopValueInjection you can override AllowSetValue

the latest (fastest) injection is this: https://valueinjecter.codeplex.com/wikipage?title=SmartConventionInjection&referringTitle=Home

It has one limitation comparing to the ConventionInjection, you don't have the values of the Source and Target Properties in the Match method but you have them in the SetValue Method and you can cancel the setting of the value to that property if you set false to the ref parameter setValue

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