I have a service that takes an object and based on the properties within will perform different actions; with this any of these properties can be null, meaning don't perform this action.
I am trying to create a very simple to use API to do this in cases where some properties can be multiple levels deep, here is an example of the current implementation
service.PerformActions(DataFactory.GetNewData<ActionsInfo> (
data => data.SomeParent = DataFactory.GetNewData<SomeParentInfo>(),
data => data.SomeParent.SomeProperty = "someValue" ));
This is a slightly simplified version and in real cases I some times have to setup multiple parent properties this way in order to set one string property at the bottom.
What I would like to do is adjust the code within the GetNewData method to handle instantiating these properties as needed so that the code could look like this:
service.PerformActions(DataFactory.GetNewData<ActionsInfo> (
data => data.SomeParent.SomeProperty = "someValue" ));
Here is my current code for GetNewData:
public static T GetNewData<T>(params Action<T>[] actions)
{
var data = Activator.CreateInstance<T>();
foreach (var action in actions)
{
try
{
action(data);
}
catch (NullReferenceException)
{
throw new Exception("The property you are attempting to set is within a property that has not been set.");
}
}
return data;
}
My first thought is to change the params
array to be Expression<Action<T>>[]
actions and somehow get a member expression for any of these parents that are null, which would allow me to use the activator to create an instance. However my experience with the more advanced features of Expression trees is slim at best.
The reason for attempting to make this API as simplistic as possible is that it is a UI testing framework that will eventually be used by non developers.
Edit: I want to add one further example of the current implementation to hopefully demonstrate that what I'm trying to do will provide for more readable code, yes there is a very slight 'side-effect' if I can pull this off but I would argue it is a helpful one.
ExampleDataFactory.GetNewData<ServicesAndFeaturesInfo>(
x => x.Property1 = ExampleDataFactory.GetNewData<Property1Type>(),
x => x.Property1.Property2 = ExampleDataFactory.GetNewData<Property2Type>(),
x => x.Property1.Property2.Property3 = ExampleDataFactory.GetNewData<Property3Type>(),
x => x.Property1.Property2.Property3.Property4 = true);
Edit 2: The classes that I'm working with here are generated from Apache Thrift struct definitions and as such I have no control over them to be able to set up some kinda of smart constructor.