【发布时间】:2014-01-17 19:18:49
【问题描述】:
这个问题与this other question有关。
我有以下方法:
public static T GetNewData<T>(params Action<dynamic>[] actions) where T : class, new()
{
dynamic dynamicData = new DeepObject();
foreach (var action in actions)
{
action(dynamicData);
}
return Converter.Convert<T>(dynamicData);
}
此方法的用户将包括较少的技术人员,甚至是非开发人员,因此更容易编写对该方法的调用越好。我现在的症结是,通过使用Action<dynamic> 作为参数类型,没有向用户提供智能感知。在上下文中,我知道智能感知应该表现得好像动态实际上是 T。
他们的方法也是我可以选择的一种方式:告诉 Visual Studio 使用类型 T 进行智能感知或将参数更改为 Action<T> 并以某种方式以编程方式将其更改为 Action<dynamic> 或 Action<DeepObject> 以便调用它会成功吗?
编辑:为了澄清,我用于 T 的类型不是 DeepObject 类型,它们不继承任何标准接口,DeepObject 的使用是允许设置嵌套类型而无需用户需要在每个级别显式实例化。这是添加动态和 DeepObject 代码之前的原始用法:
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);
这是现在的样子:
ExampleDataFactory.GetNewData<ServicesAndFeaturesInfo>(
x => x.Property1.Property2.Property3.Property4 = true);
编辑:这是基于 nmclean 回答的完全实施的解决方案
public static DataBuilder<T> GetNewData<T>() where T : class, new()
{
return new DataBuilder<T>();
}
DataBuilder 类:
public class DataBuilder<T>
{
public readonly T data;
public DataBuilder()
{
data = Activator.CreateInstance<T>();
}
public DataBuilder(T data)
{
this.data = data;
}
public DataBuilder<T> SetValue<T2>(Expression<Func<T, T2>> expression, T2 value)
{
var mExpr = GetMemberExpression(expression);
var obj = Recurse(mExpr);
var p = (PropertyInfo)mExpr.Member;
p.SetValue(obj, value);
return this;
}
public T Build()
{
return data;
}
public object Recurse(MemberExpression expr)
{
if (expr.Expression.Type != typeof(T))
{
var pExpr = GetMemberExpression(expr.Expression);
var parent = Recurse(pExpr);
var pInfo = (PropertyInfo) pExpr.Member;
var obj = pInfo.GetValue(parent);
if (obj == null)
{
obj = Activator.CreateInstance(pInfo.PropertyType);
pInfo.SetValue(parent, obj);
}
return obj;
}
return data;
}
private static MemberExpression GetMemberExpression(Expression expr)
{
var member = expr as MemberExpression;
var unary = expr as UnaryExpression;
return member ?? (unary != null ? unary.Operand as MemberExpression : null);
}
private static MemberExpression GetMemberExpression<T2>(Expression<Func<T, T2>> expr)
{
return GetMemberExpression(expr.Body);
}
}
用法:
ExampleDataFactory.GetNewData<ServicesAndFeaturesInfo>()
.SetValue(x=> x.Property1.EnumProperty, EnumType.Own)
.SetValue(x=> x.Property2.Property3.Property4.BoolProperty, true)
.Build();
【问题讨论】:
-
你为什么使用
Action<dynamic>作为你的参数类型? -
@ledbutter 我的编辑可能会更清楚地说明这一点。