Fun with C#: How to get rid of INPC using Dynamic – Part 4

With what we wrote up to the previous post, we should be able to write the following code:

var viewModel = new InvoiceItemViewModel { ProductName = “Some value" };

dynamic decorator = new DynamicDtoDecorator(viewModel);

The next step is to enable access to the properties through the decorator, like so:

decorator.ProductName = “Some new value”;
Console.WriteLine(decorator.ProductName);

Since the decorator variable above has been declared as dynamic, the compiler won’t complain about the DynamicDtoDecorator not having such a thing as a ProductName property. However, during runtime, the code will blow up when it tries to access that property. Here’s what we need to do to the DynamicDtoDecorator class so it knows how to set a value to a dynamic property:

public override bool TrySetMember(SetMemberBinder binder, object value)
{
    SetProperty(binder.Name, value);
    return true;
}

public virtual void SetProperty(string propertyName, dynamic value)
{
    if (!_members.ContainsKey(propertyName))
        throw new InvalidOperationException({0}#x22;Unregistered member: {propertyName}");
    if (_members[propertyName].Get() == value) return;
    
    _members[propertyName].Set(value);
    RaisePropertyChanged(propertyName);
}

Our DynamicDtoDecorator class inherits from DynamicObject, which provides a TrySetMember method: this method gets called during runtime whenever we try to set a member on the object. Its SetMemberBinder parameter has a Name property, which gives us the name of the member we’re trying to set (in earlier example, that’d be the “ProductName” property). The method also takes in the value we’re trying to set the member to. Finally, the method is supposed to return true or false in order to indicate whether it could successfully set the value or not.

I’ve created a SetProperty method, which is called by the TrySetMember method, just to keep things more organized. This method performs a some simple validation (making sure the given property name is registered within the decorator), sets the value on the property using our PropertyAccessor, and calls RaisePropertyChanged.

The code that allows us to get the value of a property is very similar:

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
    if (_members.ContainsKey(binder.Name))
    {
        var propertyValue = _members[binder.Name];
        result = propertyValue.Get();
        return true;
    }
    result = null;
    return false;
}

So, whenever we try to get the value of a dynamic property, a TryGetMember method is called. It takes in a GetMemberBinder, which gives us the name of the member we’re trying to access, and it also takes in an out parameter to which we set what value we want returned out of that operation. The method itself needs to return a boolean indicating whether or not the method succeeded.

That’s it! The most basic implementation of our decorator is ready: we can instantiate it passing in a ViewModel or other type of DTO, set it to the DataContext in WPF visual elements, and use DataBinding. The data displays on the UI, and should values in properties change, the UI should be updated to reflect the change.

So far, what we’re calling a decorator is really a proxy, since it doesn’t really add much functionality to the underlying object. However, once I got to this point, I started seeing other things I could use this approach for, and the class really became a decorator. But more on that on some other upcoming posts. We’re not done with this series yet!

  1. Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: