Can*_*cer 3 c# dynamic impromptu-interface
我dynamic
在视图模型中使用对象,因为我发现使用 Automapper 之类的东西不必要的开销,并且发现这种方法更加灵活和轻量级。我正在使用来自即兴界面的构建器,如下所示:
private dynamic New = Builder.New();
private dynamic GetViewModel(Product p)
{
var viewModel = New.Product( id : p.Id, name : p.Name );
viewModel.AdditionalProperty = "some additional data";
return viewModel;
}
Run Code Online (Sandbox Code Playgroud)
在某些情况下,“扩展”实际对象会比逐一重新映射所有属性更好,类似于在 JavaScript 中使用jQuery.extend()
private dynamic GetViewModel(Product p)
{
var viewModel = //create base dynamic object, that has all the members of p.
viewModel.AdditionalProperty = "some additional data";
return viewModel;
}
Run Code Online (Sandbox Code Playgroud)
这应该可以通过ExpandoObject
结合反射和迭代所有成员来实现,但我想知道是否有更干净/更整洁的解决方案。
我最终是这样实现的:
public class ExpandedObject : DynamicObject
{
private readonly IDictionary<string, object> expando = new ExpandoObject();
public ExpandedObject(object o)
{
foreach (var propertyInfo in o.GetType().GetProperties(BindingFlags.Public|BindingFlags.Instance))
{
this.expando[propertyInfo.Name] = Impromptu.InvokeGet(o, propertyInfo.Name);
}
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return this.expando.TryGetValue(binder.Name, out result);
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
this.expando[binder.Name] = value;
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
和测试:
[TestFixture]
public class ExpandedObjectTest
{
[Test]
public void Can_add_new_properties_to_expanded_object()
{
dynamic expanded = new ExpandedObject(new object());
var data = "some additional data";
expanded.data = data;
Assert.AreEqual(data, expanded.data);
}
[Test]
public void Copies_existing_properties()
{
var obj = new { id = 5 };
dynamic expanded = new ExpandedObject(obj);
Assert.AreEqual(obj.id, expanded.id);
}
}
Run Code Online (Sandbox Code Playgroud)
从我的测试来看,这使用了Impromptu.InvokeGet()
而不是PropertyInfo.GetValue()
因为Impromptu.InvokeGet()
使用了 DLR,因此比使用反射快了大约 2.5 倍。总体而言,该方法运行得相当快,并且最多 10,000 个对象的开销几乎不存在。
我应该指出,这不会用于扩展其他ExpandoObject
或类似的内容,但这实际上并不是必要的。