Bill
Bill

Reputation: 614

Update a specific property with generics (Winform C#)

Apologies as I am new to generics (which is what I believe is needed in this scenario).

I want to pass the BindingList variable to a method that performs an update on a defined property, and then returns a pass/fail (true/false) value. This appears to be harder than I thought it would be, so could use some help. Here is working and non-working code.

First, I have a class with a BindingList (working):

public class BookMetaData : INotifyPropertyChanged
{
    private string _bookMetaDataTitle;
    [DescriptionLocalized(typeof(ResourcesClassBooks), "BookMetaDataTitleComment")]
    [DisplayNameLocalized(typeof(ResourcesClassBooks), "BookMetaDataTitleDisplayName")]
    public string BookMetaDataTitle { get { return _bookMetaDataTitle; } set { SetField(ref _bookMetaDataTitle, value, "BookMetaDataTitle"); } }

    #region handle property changes
    public event PropertyChangedEventHandler PropertyChanged;
    protected bool SetField<T>(ref T field, T value, string propertyName)
    {
        //if the value did not change, do nothing.
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        //the value did change, so make the modification.
        field = value;
        return true;
    }
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
}

Next, I create a variable that represents the binding list (working):

BindingList<BookMetaData> bookMetaData = new BindingList<BookMetaData>(); //metadata for the books

Prepare to send the class variable and specific property to update to a generic method. Please note, this technically works, but the remaining code does not:

private bool Test()
{
    //the code below would probably be in a foreach loop and would not pass a single index.
    ProcessBookTitle(bookMetaData, 0, typeof(BookMetaData).GetProperty(nameof(BookMetaData.BookMetaDataCoverage)));
    return true;
}

I want this generic method (is it called a method?) to update the BindingList class variable's specified property. If something goes wrong in the general business logic, that return false. Otherwise, return true (not working):

private void ProcessBookTitle<T>(BindingList<T> bindingList, int classIndex, PropertyInfo prop)
{
    try
    {
        //do some things...
        //If I manually wrote the next line, it would look like this:
        //bookMetaData[0].BookMetaDataTitle = "My Book Title";
        bindingList[classIndex].prop = "My Book Title"; //error = 'T' does not contain the information for 'prop'...
        //maybe do some other things...
        return true; //cannot find a way to return bool.
    }
        catch
        {
            //something went wrong somewhere, so return false.
            return false; //does not work because cannot return a bool.
        }
    }

Is there a way I can send the name of the class variable and the property to update to another method? Also, is it possible to do this within a method that returns bool (and or some other way of returning success or failure)?

Thanks in advance for any help you can provide.

EDIT: The requirement to return a bool is to ensure the passing method knew whether the overall process was successful. Updated code to show this.

Upvotes: 2

Views: 1979

Answers (1)

John Ephraim Tugado
John Ephraim Tugado

Reputation: 765

You can use reflection for this as @Yacoub Massad mention. If you are wondering how then it's like this. What we are doing here is getting the type of generic type T and access its property information. Now since you mentioned reading from file, parsing information etc, I suggest you look into Delegate Actions With Return Values. But that it self is another story to tell.

    static private bool ProcessBookTitle<T>(BindingList<T> bindingList, int classIndex, string propertyName) 
        where T : class
    {
        try
        {
            Type type = typeof(T);
            PropertyInfo propertyInfo = type.GetProperty(propertyName);

            object val = "Do some processing whatever here.";

            propertyInfo.SetValue(bindingList[classIndex], Convert.ChangeType(val, propertyInfo.PropertyType), null);

            return true;
        }
        catch (Exception ex)
        {
            // do something with the exception

            return false;
        }
    }

Upvotes: 2

Related Questions