C#通用类型;无法绑定到属性或列

时间:2015-02-11 21:20:57

标签: c# generics data-binding

所以我有这个Generic类型的类,它使用System.Reflection从类中获取所有公共变量并将它们呈现为控件。

但是我需要能够将这些变量用作控件的DataBindings,这样当控件接收输入时,该输入会保存到相应的变量中。

这是我到目前为止所得到的,但我得到的是“不能绑定到属性或列”。错误。

班级:

public class ComponentControl<T> where T : Component
{
   private T component;

   public ComponentControl(T component)
   {
      this.component = component;
   }
}

不能工作的部分:

foreach (var f in type.GetFields().Where(f => f.IsPublic))
{
   TextBox control = new TextBox();
   Binding binding = new Binding("Text", component, f.Name, false, DataSourceUpdateMode.OnPropertyChanged);
   control.DataBindings.Add(binding);
}

1 个答案:

答案 0 :(得分:0)

我认为你只能绑定到自定义对象的属性,而不是字段。这似乎有点矫枉过正,但如果有一种更简单的方法,我相信有人会纠正我..

假设您不想将字段更改为属性,并且您确实想要使用绑定,则可以生成一种要绑定的DTO。例如,以下是绑定方式,因此请使用proxyType而不是实际类型。

ComponentControl<int> component = new ComponentControl<int>() { A = "A", B = 1, C = 2 };
Type type = component.GetType();            
dynamic proxyType = DynamicProxyGenerator.GetInstanceFor<ComponentControl<int>>(component);            

foreach (var f in type.GetFields().Where(f => f.IsPublic))
{
    TextBox control = new TextBox();
    Binding binding = new Binding("Text", proxyType, f.Name, false, DataSourceUpdateMode.OnPropertyChanged);

    control.DataBindings.Add(binding);
}

以下是DynamicProxyGenerator生成该代码的代码。

public static class DynamicProxyGenerator
{
    public static object GetInstanceFor<T>(T toBind)
    {
        Type typeOfT = typeof(T);

        AssemblyName assName = new AssemblyName("testAssembly");
        var assBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assName, AssemblyBuilderAccess.RunAndSave);            
        var moduleBuilder = assBuilder.DefineDynamicModule("dynamicModule", "dynamicBinder.dll");
        var typeBuilder = moduleBuilder.DefineType(typeOfT.Name + "Proxy", TypeAttributes.Public | TypeAttributes.Class);            
        FieldBuilder bindingSourceField = typeBuilder.DefineField("BindingSource", typeOfT, FieldAttributes.Public);            

        foreach (FieldInfo toCopyField in typeOfT.GetFields()) 
        {
            PropertyBuilder propBuilder = typeBuilder.DefineProperty(toCopyField.Name, System.Reflection.PropertyAttributes.None, toCopyField.FieldType, null);                             

            MethodBuilder getter = typeBuilder.DefineMethod("get_" + toCopyField.Name,  MethodAttributes.Public, toCopyField.FieldType, Type.EmptyTypes);                
            ILGenerator getIL = getter.GetILGenerator();
            getIL.Emit(OpCodes.Ldarg_0);
            getIL.Emit(OpCodes.Ldfld, bindingSourceField);
            getIL.Emit(OpCodes.Ldfld, toCopyField);
            getIL.Emit(OpCodes.Ret);
            propBuilder.SetGetMethod(getter);

            MethodBuilder setter = typeBuilder.DefineMethod("set_" + toCopyField.Name,  MethodAttributes.Public, null, new Type[] { toCopyField.FieldType });
            ILGenerator setIL = setter.GetILGenerator();
            setIL.Emit(OpCodes.Ldarg_0);
            setIL.Emit(OpCodes.Ldfld, bindingSourceField);
            setIL.Emit(OpCodes.Ldarg_1);                
            setIL.Emit(OpCodes.Stfld, toCopyField);
            setIL.Emit(OpCodes.Ret);
            propBuilder.SetSetMethod(setter);                
        }

        Type constructedType = typeBuilder.CreateType();
        dynamic instance = Activator.CreateInstance(constructedType);
        instance.BindingSource = toBind;

        return instance;
    }
}  

所以这样做就是动态创建一个看起来像这样的新类型,你可以将它用作绑定源,作为控件和对象的间隔。

public class ComponentControlProxy
{
    public ComponentControl<int> BindingSource;

    public string A 
    {
        get 
        {
            return BindingSource.A;
        }
        set 
        {
            BindingSource.A = value;
        }
    }

    .. etc
}