wootscootinboogie
wootscootinboogie

Reputation: 8695

Get list of property names using interface method

I have two custom types Customer and Employee which implement the interface ITablefy. This interface has only one method, GetPropertyList which returns a list of strings of the property names of the object that implements it. I have a web service which looks like:

public string ReturnPropertyNames(ITablefy i)
{
    List<string> propList = new List<string>();
    TableFactory factory = new TableFactory();
    ITablefy table = factory.CreateTable(i);
    propList = table.GetPropertyList(table);
    return propList[1];
}

so in this example the Factory creates a concrete type that implements ITablefy

I realized when I had a problem when both of my classes Customer and Employee implemented their GetPropertyList methods exactly the same:

//property list is a private member variable in each class
    public List<string> GetPropertyList(ITablefy i)
    {
        TableFactory factory = new TableFactory();
        ITablefy table = factory.CreateTable(i);
        foreach (var propInfo in table.GetType().GetProperties())
        {
            propertyList.Add(propInfo.Name);
        }
        return propertyList;
    }

Rather than copy and paste that code I'm looking for a better solution to what I have currently. If I only want certain types to use the GetPropertyList method how can I control that without having to copy and paste this same code? Harcoding the type to create in each class doesn't seem like a good solution to me. Employee and Customer don't logically make sense to use inheritance either. What's a proper solution for something like this?

factory:

public class TableFactory
{
    public ITablefy CreateTable(ITablefy i)
    {
        if (i is Employee)
        {
            return new Employee();
        }
        else if (i is Customer)
        {
            return new Customer();
        }
        else
        {
            return null;
        }
    }
}

Upvotes: 0

Views: 1373

Answers (2)

plinth
plinth

Reputation: 49179

public static List<string> GetPropertyNames(this Object o)
{
    List<string> names = new List<string>

    foreach (PropertyInfo prop in o.GetType().GetProperties())
        names.Add(prop.Name);
    return names;
}

Now you can implement ITablefy in terms of any object.GetPropertyNames() using the extension method above.

There are a few questions that comes to my mind:

  1. If It's so easy to do generically, why are you even using the interface?
  2. Shouldn't you be checking properties for public accessors?
  3. Shouldn't your interface be returning a more general type like IEnumerable<string> or ICollection<string>?
  4. Wouldn't the interface be better designed to filter out property names that you don't want? That way you could assume all public properties are part of the set except those that aren't.

You make the interface be something like:

public interface IPropertyInfoFilterProvider {
    public Func<PropertyInfo, bool> PropertyInfoSkipFilter { get; set; }
}

or

public interface IPropertyNameFilterProvider {
    public Func<string, bool> PropertyNameSkipFilter { get; set; }
}

and then you can initialize the default to (prop) => false.

so now you can harvest the property names automagically and in one place and let implementations determine what gets taken and what doesn't and your harvesting code could use that filter in a linq where clause.

Upvotes: 1

Derek
Derek

Reputation: 8763

You could make it an extension method on ITablefy. Or a static method on ITablefy

Upvotes: 1

Related Questions