marcusoftnet / SpecFlow.Assist.Dynamic

Extension methods to create dynamic objects from SpecFlow tables
https://github.com/marcusoftnet/SpecFlow.Assist.Dynamic
MIT License
51 stars 27 forks source link

Ability to specify property name casing rules, or a way to match property names #19

Open icnocop opened 6 years ago

icnocop commented 6 years ago

I'd like the ability to specify the property name casing rules, or a way to match property names, because the current convention doesn't create the expected property names.

For example, add the following scenario in .\Specs\DynamicInstancesFromTable.feature:

Scenario: Create dynamic instance from table with specific property name
    When I create a dynamic instance from this table
        | Customer ID |
        | 123         |
    Then the CustomerID property should equal '123'

And add the following step in .\Specs\Steps\DynamicInstanceCreationSteps.cs:

        [Then(@"the CustomerID property should equal '(.*)'")]
        public void ThenTheCustomerIDPropertyShouldEqual(int expectedValue)
        {
            ((int)State.OriginalInstance.CustomerID).Should().Equal(expectedValue);
        }

Result:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException : 'System.Dynamic.ExpandoObject' does not contain a definition for 'CustomerID'

The current convention will create an ExpandoObject with the property CustomerId.

The issue occurs when I try to assign the properties from the ExpandoObject to fields in the database.

In my case, the field in the database is CustomerID.

As a work-around I have to search for the property name without case sensitivity.

The issue can be resolved in two ways.

  1. Add the ability to specify one of the following property name casing rules: a. Do not change the case b. Only change the case on the first letter of every word

  2. Since I already have a type with properties I want the property names in the ExpandoObject to match with, add the ability to pass the type during the creation of the dynamic instance (using the generic syntax for example). I can't use SpecFlow's built-in support for creating objects because I'm updating entities in a database from the table, and I specify only the fields I want updated in the table.

Thank you.

icnocop commented 6 years ago

I created PR #21 which allows the user to optionally specify a custom property name mapper.

If not specified, the default property name mapper will be used.

For example:

    public class CustomPropertyNameMapper : IPropertyNameMapper
    {
        public string Map(string header)
        {
            return header.Replace(" ", string.Empty);
        }
    }

It can then be used as follows:

            Options options = new Options
            {
                PropertyNameMapper = new CustomPropertyNameMapper()
            };
            dynamic instance = table.CreateDynamicInstance(options);

Thank you.

notnotchris commented 4 years ago

I've just had this issue today where the automatic property name formatting was causing me problems. I liked the idea suggested above by @icnocop and it would have provided a way of solving my problem (by preserving property names). Therefore, I've pinched a couple of his ideas and created PR #27 that allows a property name formatter to be specified.

I'd be grateful if it could be considered for inclusion and for any comments.