C# 如何动态创建绑定代理?
我有一个配置对象,它有一个C# 如何动态创建绑定代理?,c#,.net,winforms,data-binding,C#,.net,Winforms,Data Binding,我有一个配置对象,它有一个enum,我想把一堆RadioButton绑定到同一个属性。正如我看到自己重复的那样,有时我试图想出一个通用的解决方案,将多个项绑定到同一个属性。我找到的解决方案是创建一个执行表达式的代理。请参阅下面的代码 public enum GenderEnum { Male, Female } public class DataClass { public GenderEnum Gender { get; set; } } class Express
enum
,我想把一堆RadioButton
绑定到同一个属性。正如我看到自己重复的那样,有时我试图想出一个通用的解决方案,将多个项绑定到同一个属性。我找到的解决方案是创建一个执行表达式的代理。请参阅下面的代码
public enum GenderEnum
{
Male,
Female
}
public class DataClass
{
public GenderEnum Gender { get; set; }
}
class ExpressionBinder<T>
{
public Func<T> Getter;
public Action<T> Setter;
public T Value
{
get { return Getter.Invoke(); }
set { Setter.Invoke(value); }
}
public ExpressionBinder(Func<T> getter, Action<T> setter)
{
Getter = getter;
Setter = setter;
}
}
不幸的是,我只能说我想如何使用它
radioMale.DataBindings.Add("Checked",
new ComparisonBinder<ConfigClass>((c) c.Gender, GenderEnum.Male),
"Value");
radioFemale.DataBindings.Add("Checked",
new ComparisonBinder<ConfigClass>((c) c.Gender, GenderEnum.Female),
"Value");
用法:
radioMale.DataBindings.Add("Checked",
new ComparisonBinder<DataClass,GenderEnum>(DataObj, (x) => x.Gender, GenderEnum.Male), "Value");
radioFemale.DataBindings.Add("Checked",
new ComparisonBinder<DataClass,GenderEnum>(DataObj, (x) => x.Gender, GenderEnum.Female), "Value");
radioMale.DataBindings.Add(“选中”,
新的比较指标(DataObj,(x)=>x.性别,GenderEnum.男性),“值”);
radioFemale.DataBindings.Add(“选中”,
新的比较指标(DataObj,(x)=>x.性别,GenderEnum.女性),“值”);
我认为这可以通过使用PropertyInfo
和一些lambda magic来实现:
class ComparisonBinder<TSource,TValue> : ExpressionBinder<bool>
{
public ComparisonBinder(TSource source, Expression<Func<TSource, bool>> propertyLambda, TValue comparisonValue) :base(null,null)
{
var propertyInfo = GetPropertyInfo<TSource,bool>(source, propertyLambda);
this.Getter = () => comarisonValue.Equals((TValue)propertyInfo.GetValue(source));
this.Setter = (bool value) => { if(value) propertyInfo.SetValue(source, comparisonValue); };
}
}
class ComparisonBinder:ExpressionBinder
{
公共ComparisonBinder(t源代码,表达式propertyLambda,TValue comparisonValue):基(null,null)
{
var propertyInfo=GetPropertyInfo(来源,propertyLambda);
this.Getter=()=>comarisonValue.Equals((TValue)propertyInfo.GetValue(source));
this.Setter=(bool值)=>{if(value)propertyInfo.SetValue(source,comparisonValue);};
}
}
用法:
radioMale.DataBindings.Add("Checked",
new ComparisonBinder<ConfigClass, GenderEnum>(config, c => c.Gender, GenderEnum.Male),
"Value");
radioFemale.DataBindings.Add("Checked",
new ComparisonBinder<ConfigClass, GenderEnum>(config, c => c.Gender, GenderEnum.Female),
"Value");
radioMale.DataBindings.Add(“选中”,
新的ComparisonBinder(config,c=>c.Gender,GenderEnum.Male),
“价值”);
radioFemale.DataBindings.Add(“选中”,
新的ComparisonBinder(config,c=>c.Gender,GenderEnum.Female),
“价值”);
我还没有测试它,但希望您能够修复任何错误并使用此解决方案
GetPropertyInfo():复制自
publicpropertyinfo GetPropertyInfo(
t来源:,
表达式属性(MBDA)
{
类型类型=类型(t源);
MemberExpression member=propertyLambda.Body作为MemberExpression;
if(成员==null)
抛出新ArgumentException(string.Format(
表达式“{0}”引用的是方法,而不是属性,
propertyLambda.ToString());
PropertyInfo-propInfo=成员。成员为PropertyInfo;
if(propInfo==null)
抛出新ArgumentException(string.Format(
表达式“{0}”引用的是字段,而不是属性,
propertyLambda.ToString());
if(type!=propInfo.ReflectedType&&
!type.IsSubclassOf(propInfo.ReflectedType))
抛出新ArgumentException(string.Format(
表达式{0}引用的属性不是来自类型{1},
propertyLambda.ToString(),
类型);
返回propInfo;
}
我刚刚提出了一个与此非常接近的代码。但是谢谢!我将合并这个GetPropertyInfo
方法,因为我没有检查我应该检查的所有内容,并更新问题以供进一步参考。现在我要做双向跳跃。但这是另一个问题。。。
radioMale.DataBindings.Add("Checked",
new ComparisonBinder<DataClass,GenderEnum>(DataObj, (x) => x.Gender, GenderEnum.Male), "Value");
radioFemale.DataBindings.Add("Checked",
new ComparisonBinder<DataClass,GenderEnum>(DataObj, (x) => x.Gender, GenderEnum.Female), "Value");
class ComparisonBinder<TSource,TValue> : ExpressionBinder<bool>
{
public ComparisonBinder(TSource source, Expression<Func<TSource, bool>> propertyLambda, TValue comparisonValue) :base(null,null)
{
var propertyInfo = GetPropertyInfo<TSource,bool>(source, propertyLambda);
this.Getter = () => comarisonValue.Equals((TValue)propertyInfo.GetValue(source));
this.Setter = (bool value) => { if(value) propertyInfo.SetValue(source, comparisonValue); };
}
}
radioMale.DataBindings.Add("Checked",
new ComparisonBinder<ConfigClass, GenderEnum>(config, c => c.Gender, GenderEnum.Male),
"Value");
radioFemale.DataBindings.Add("Checked",
new ComparisonBinder<ConfigClass, GenderEnum>(config, c => c.Gender, GenderEnum.Female),
"Value");
public PropertyInfo GetPropertyInfo<TSource, TProperty>(
TSource source,
Expression<Func<TSource, TProperty>> propertyLambda)
{
Type type = typeof(TSource);
MemberExpression member = propertyLambda.Body as MemberExpression;
if (member == null)
throw new ArgumentException(string.Format(
"Expression '{0}' refers to a method, not a property.",
propertyLambda.ToString()));
PropertyInfo propInfo = member.Member as PropertyInfo;
if (propInfo == null)
throw new ArgumentException(string.Format(
"Expression '{0}' refers to a field, not a property.",
propertyLambda.ToString()));
if (type != propInfo.ReflectedType &&
!type.IsSubclassOf(propInfo.ReflectedType))
throw new ArgumentException(string.Format(
"Expresion '{0}' refers to a property that is not from type {1}.",
propertyLambda.ToString(),
type));
return propInfo;
}