This project has moved. For the latest updates, please go here.

Using EventAggregator with generics?

Aug 23, 2012 at 7:38 PM

Hi Jeremy - I'm using (and loving!) Jounce in my current application. I have implemented a "PeoplePicker" child window that provides a user interface for selecting people from AD and then assigning the selected person to a target person attribute.

The main entity (Deployments) has four person attributes: Assignee, AltContact, Owner, and ITContact. The PeoplePicker publishes a message when the selection is made, and the current view receives the message and updates the desired person attribute.

I'm passing the field name, navigation property name, and an ADPeople entity in the message. The viewmodel receiving the message updates the person attribute using reflection (this works fine):

protected override void UpdatePerson(string fieldName, string navPropName, ADPeople person)
{
    string nt = person.nt;

    Type type = SelectedDeploymentItem.GetType();       //SelectedDeploymentItem is bound to the SelectedItem in the DataGrid
    PropertyInfo prop = type.GetProperty(fieldName);    //Get a reference to the specific person field (there are four of them)
    prop.SetValue(SelectedDeploymentItem, nt, null);    //Set the foreign key value
    prop = type.GetProperty(navPropName);               //get a reference to the navigation property for this foreign key
    prop.SetValue(SelectedDeploymentItem, person, null);//set the ADPeople value. This works when this class uses the same instance 
}

This is the message that is passed:

public class MessagePersonSelected
{
    public ADPeople Person { get; private set; }
    public string PersonFieldName { get; private set; }
    public string NavPropName { get; private set; }
    private MessagePersonSelected(string fldName, string navProp, ADPeople person)
    {
        PersonFieldName = fldName;
        Person = person;
        NavPropName = navProp;
    }

    public static MessagePersonSelected Create(string fldName, string navProp, ADPeople person)
    {
        return new MessagePersonSelected(fldName, navProp, person);
    }
}

The viewmodel of the current form receives the message and then passes the message payload to the UpdatePerson method.

If I expose the SelectedDeploymentItem to the viewmodel that publishes the message, is there a way to use a generic reference to the properties instead of by name? Instead of:

var newperson = MessagePersonSelected.Create(FieldName, NavPropName, SelectedPerson);

Something more like:

var newperson = MessagePersonSelected.Create(() => DepUserID, () => Assignee, SelectedPerson);

I'm not sure if this is possible, or if it is, I don't know how to declare the properties of the message.

Thanks!

Aug 23, 2012 at 11:49 PM

Have you had a look at Jounce\Core\Model\BaseNotify.cs ?  The ExtractPropertyName function is called (indirectly) when you RaisePropertyChanged(()=>myProp).

The parameter is declared as Expression<Func<T>>.  You should be able to implement a similar approach for your MessagePersonSelected.Create parameters.

Aug 24, 2012 at 12:48 AM

Yep, that's where I got the idea that it might be possible, but I'm not familliar enough with generics to compose a new message using them...

Aug 24, 2012 at 1:06 AM

It is only the static factory that you need to be generic, the message can stay non-generic.  I would think that you should be able to change your static factory method to

public static MessagePersonSelected Create<T,U>(
                      Expression<Func<T>> field,
                      Expression<Func<U>> navigation,
                      ADPeople person)
{
    return new MessagePersonSelected(
                       ExtractPropertyName(field),
                       ExtractPropertyName(navigation),
                       person);
} 

You will only be able to use the ExtractPropertyName method if you move the static factory in to your ViewModel (so that it has visibilty of the inherited BaseNotify class). Otherwise you will need to implement a version of ExtractPropertyName somewhere that is accessible to your message factory.