如何获得对属性的setter的引用?

时间:2011-04-13 00:15:38

标签: c# .net asp.net

我有一些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),可以与该类的任何实例一起使用吗?

我知道这可以通过反射来完成,但我项目中的其他开发人员都存在性能问题,所以如果可能的话,我更倾向于使用非反射解决方案。

谢谢!

5 个答案:

答案 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)