3

I get an exception when I try to set a nested member Property using FastMember. For example when having these classes

public class A
{
    public B First { get; set; }
}

public class B
{
    public string Second { get; set; }
}

and I want to set First.Second of an instance to "hello".

var b = new B{ Second = "some value here" };
var a = new A{ First = b };
var accessor = ObjectAccessor.Create(a);
accessor["First.Second"] = value; // this does not work and gives ArgumentOutOfRangeException

I can't split it up into ["First"]["Second"] because I don't know the depth at this point. Is there a magical access for nested properties or do I have to split the hierarchy myself?

Mahdi
  • 3,199
  • 2
  • 25
  • 35
Beachwalker
  • 7,685
  • 6
  • 52
  • 94

3 Answers3

3

I solved the problem recursively using an Extension Method this way:

public static class FastMemberExtensions
{
    public static void AssignValueToProperty(this ObjectAccessor accessor, string propertyName, object value)
    {
        var index = propertyName.IndexOf('.');

        if (index == -1)
        {
            accessor[propertyName] = value;
        }
        else
        {
            accessor = ObjectAccessor.Create(accessor[propertyName.Substring(0, index)]);
            AssignValueToProperty(accessor, propertyName.Substring(index + 1), value);
        }
    }        
}

... and this is started as follows:

ObjectAccessor.Create(a).AssignValueToProperty("First.Second", "hello")
Beachwalker
  • 7,685
  • 6
  • 52
  • 94
2

You need to traverse the object graph using multiple ObjectAccessor instances.

public static void UseFastMember()
{
    var b = new B { Second = "some value here" };
    var a = new A { First = b };
    var value = "hello";
    var a_accessor = ObjectAccessor.Create(a);
    var first = a_accessor["First"];
    var b_accessor = ObjectAccessor.Create(first);
    b_accessor["Second"] = value;
}
Jeffrey Patterson
  • 2,342
  • 1
  • 13
  • 9
  • thank you for the info, thought there might be an already builtin solution. I posted the recursive function I use now. any Ideas how to solve the issue with nullable types? it is the question here: http://stackoverflow.com/questions/40306591/assign-value-to-nullablet-using-fastmember – Beachwalker Oct 28 '16 at 14:01
1

Hats off to @Beachwalker for the inspiration. But should you be using TypeAccessor as opposed to ObjectAccessor this is an extension method I've had much success with:

public static class TypeAccessorExtensions
{
    public static void AssignValue<T>(this TypeAccessor accessor, T t, MemberSet members, string fieldName, object fieldValue)
    {
        var index = fieldName.IndexOf('.');

        if (index == -1)
        {
            if (members.Any(m => string.Equals(m.Name, fieldName, StringComparison.OrdinalIgnoreCase)))
                accessor[t, fieldName] = fieldValue;
        }
        else
        {
            string fieldNameNested = fieldName.Substring(0, index);
            var member = members.FirstOrDefault(m => string.Equals(m.Name, fieldNameNested, StringComparison.OrdinalIgnoreCase));

            if (member != null)
            {
                var nestedAccesor = TypeAccessor.Create(member.Type);
                var tNested = accessor[t, fieldNameNested];

                if (tNested == null)
                {
                    tNested = Activator.CreateInstance(member.Type);
                    accessor[t, fieldNameNested] = tNested;
                }

                nestedAccesor.AssignValue(tNested, nestedAccesor.GetMembers(), fieldName.Substring(index + 1), fieldValue);
            }

        }
    }
}
pim
  • 12,019
  • 6
  • 66
  • 69
  • 1
    It's me who also asked the question and 'cause nobody had an answer that time which solves this problem I did myself. However, thanks for the hats. ;-) – Beachwalker Jul 17 '17 at 15:55
  • 1
    hehe saw that! love the "self join" (wow that was lame) -- great work either way! – pim Jul 17 '17 at 15:58