我有一个服务,它接受一个对象,并根据其中的属性执行不同的操作;这样,这些属性中的任何一个都可以为 null,这意味着不执行此操作。
我正在尝试创建一个非常简单易用的 API 来在某些属性可能深达多个级别的情况下执行此操作,这是当前实现的示例
service.PerformActions(DataFactory.GetNewData<ActionsInfo> (
data => data.SomeParent = DataFactory.GetNewData<SomeParentInfo>(),
data => data.SomeParent.SomeProperty = "someValue" ));
这是一个稍微简化的版本,在实际情况下,我有时必须以这种方式设置多个父属性,以便在底部设置一个字符串属性。
我想要做的是调整 GetNewData 方法中的代码以根据需要处理实例化这些属性,以便代码如下所示:
service.PerformActions(DataFactory.GetNewData<ActionsInfo> (
data => data.SomeParent.SomeProperty = "someValue" ));
这是我当前的 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;
}
我的第一个想法是改变params
数组为Expression<Action<T>>[]
操作并以某种方式获取任何为空的父级的成员表达式,这将允许我使用激活器创建一个实例。然而,我对表达式树的更高级功能的体验充其量是微乎其微的。
尝试使这个 API 尽可能简单的原因是,它是一个 UI 测试框架,最终将被非开发人员使用。
Edit:我想添加当前实现的另一个示例,以希望证明我正在尝试做的事情将提供更具可读性的代码,是的,如果我能实现这一点,会有一个非常轻微的“副作用”,但我会争辩这是一个很有帮助的。
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:我在这里使用的类是从 Apache Thrift 结构定义生成的,因此我无法控制它们来设置某种智能构造函数。