我有一些asp.net代码,它使用发布表单中的值填充LINQ to SQL对象(所有字符串字段)中的字段:
userSelections.A = Request.Form["A"];
userSelections.B = Request.Form["B"];
userSelections.C = Request.Form["C"];
userSelections.D = Request.Form["D"];
我想将表单字段的名称和关联的setter对象存储在表中,因此我可以遍历整个集合而无需编写一堆重复代码。
有没有办法让代理人获得属性设定者?也就是说,我有类 myClass ,字符串属性 myProperty 。我可以获得一个委托,例如 void myPropertySetterDelegate(string val,MyClass this),可以与该类的任何实例一起使用吗?
我知道这可以通过反射来完成,但我项目中的其他开发人员都存在性能问题,所以如果可能的话,我更倾向于使用非反射解决方案。
谢谢!
答案 0 :(得分:6)
您可以使用lambda:
Action<MyClass, string> myPropertySetter = (mc, s) => mc.MyProperty = s;
你有一个MyClass
的实例:
MyClass something = repo.GetMyClass();
myPropertySetter(something, valueFromSomewhere);
现在,按照你的例子:
Dictionary<string, Action<MyClass, string>> setters = new Dictionary<string, Action<MyClass, string>>();
setters.Add("A", Action<MyClass, string> myPropertySetter = (mc, s) => mc.A = s);
[...]
随后:
MyClass something = getFromSomewhere();
foreach (string key in Request.Form.Keys)
{
setters[key](something, Request.Form[key]);
}
答案 1 :(得分:4)
您可以使用反射来获取有关您尝试绑定到请求的类型的信息,然后生成动态方法(应该将它们缓存以便重用)以使执行速度非常快。
public static Action<object, object> CreateSetter(FieldInfo field)
{
DynamicMethod dm = new DynamicMethod("DynamicSet", typeof(void),
new Type[] { typeof(object), typeof(object) }, field.DeclaringType, true);
ILGenerator generator = dm.GetILGenerator();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldarg_1);
if (field.FieldType.IsValueType)
generator.Emit(OpCodes.Unbox_Any, field.FieldType);
generator.Emit(OpCodes.Stfld, field);
generator.Emit(OpCodes.Ret);
return (Action<object, object>)dm.CreateDelegate(typeof(Action<object, object>));
}
答案 2 :(得分:1)
从this answer复制:
Action<int> valueSetter = (Action<int>)Delegate.CreateDelegate(typeof(Action<int>), tc, tc.GetType().GetProperty("Value").GetSetMethod());
是的,这会使用反射,但会产生更高效的代理。此外,“反思”与“不反思”之间没有明确的界限。例如,Delegate
类型带有许多接受Type
的方法,Type
基本上由反射组成。那么使用反射是否使用Delegate
?
答案 3 :(得分:0)
Action<string, MyClass> propertySetter = (val, @this) => { @this.Property = val; }
答案 4 :(得分:0)