Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有办法使C#binding静态工作?_C#_Language Features - Fatal编程技术网

有没有办法使C#binding静态工作?

有没有办法使C#binding静态工作?,c#,language-features,C#,Language Features,这可能适用于其他地方,但在WinForms中,当我使用绑定时,我发现许多方法都希望使用要绑定到的属性的名称。比如: class Person { public String Name { get { ... } set { ... } } public int Age { get { ... } set { ... } } } class PersonView { void Bind(Person p) { nameControl.Bind(p,

这可能适用于其他地方,但在WinForms中,当我使用绑定时,我发现许多方法都希望使用要绑定到的属性的名称。比如:

class Person
{
    public String Name { get { ... } set { ... } }
    public int Age { get { ... } set { ... } }
}

class PersonView
{
    void Bind(Person p)
    {
        nameControl.Bind(p,"Name");
        ageControl.Bind(p,"Age");
    }
}
ageControl.Bind(p,stringof(p.Age).Name);
我一直面临的最大问题是“Name”和“Age”被指定为字符串。这意味着,如果有人重命名了Person的某个属性,编译器将毫无帮助。代码可以很好地编译,但是绑定会被破坏

有没有一个标准的方法来解决我错过的问题?我觉得我需要一些关键字,可能叫做stringof来匹配现有的typeof。您可以使用它,例如:

class Person
{
    public String Name { get { ... } set { ... } }
    public int Age { get { ... } set { ... } }
}

class PersonView
{
    void Bind(Person p)
    {
        nameControl.Bind(p,"Name");
        ageControl.Bind(p,"Age");
    }
}
ageControl.Bind(p,stringof(p.Age).Name);
stringof可以返回一些类,这些类具有获取完整路径、部分路径或字符串的属性,因此您可以自己解析它


这样的事情已经可以做了吗?

您可以使用反射来查找名称;-)

这当然是一个循环引用,您可以使用您认为是的名称来查找相同的名称(或者不查找任何内容,这意味着该属性已重命名…但是有一个想法(或者更确切地说,是一个技巧):通过对希望使用的属性进行“不做任何事”引用,可以在编译时确认该属性仍然存在。唯一的问题是,如果有人只是交换各种属性名称;在这种情况下,名称仍然存在(没有编译时错误),但具有不同的应用程序级别语义(应用程序输出中可能出现的意外情况)

看看我在另一个问题中发布的这个,它可以帮助您!(但只有在您使用.NET 3.5时)

致以最诚挚的问候

Oliver Hanappi

如前所述,您可以通过表达式树实现这一点

受保护的静态字符串GetPropertyName(表达式)
{
if(expression.NodeType==ExpressionType.Lambda&&expression.Body.NodeType==ExpressionType.MemberAccess)
{
PropertyInfo prop=(expression.Body作为MemberExpression.Member作为PropertyInfo;
如果(prop!=null)
{
返回道具名称;
}
}
抛出新ArgumentException(“表达式”,“非属性表达式”);
}
...
绑定(p,GetPropertyName((Person p)=>p.Age));

您可以使用表达式来检查编译器绑定。 例如,在当前的一个项目中,我们设置了如下绑定:

DataBinder
    .BindToObject(this)
    .ObjectProperty(c => c.IsReadOnly)
        .Control(nameTextBox, n => n.ReadOnly)
        .Control(addressControl, n => n.ReadOnly)
支持此样式的代码分为几个类:

public static class DataBinder
{
    public static DataBinderBindingSourceContext<TDataSource> BindToObject<TDataSource>(TDataSource dataSource)
    {
        return new DataBinderBindingSourceContext<TDataSource>(dataSource);
    }
}

public class DataBinderBindingSourceContext<TDataSource> 
{
    public readonly object DataSource;

    public DataBinderBindingSourceContext(object dataSource)
    {
        DataSource = dataSource;
    }

    public DataBinderControlContext<TDataSource, TProperty> ObjectProperty<TProperty>(Expression<Func<TDataSource, TProperty>> property)
    {
        return new DataBinderControlContext<TDataSource, TProperty>(this, property);
    }
}

public class DataBinderControlContext<TDataSource, TProperty>
{
    readonly DataBinderBindingSourceContext<TDataSource> BindingSourceContext;
    readonly string ObjectProperty;

    public DataBinderControlContext
        (
            DataBinderBindingSourceContext<TDataSource> bindingSourceContext,
            Expression<Func<TDataSource, TProperty>> objectProperty
        )
    {
        BindingSourceContext = RequireArg.NotNull(bindingSourceContext);
        ObjectProperty = ExpressionHelper.GetPropertyName(objectProperty);
    }

    public DataBinderControlContext<TDataSource, TProperty> Control<TControl>(TControl control, Expression<Func<TControl, TProperty>> property)
        where TControl : Control
    {
        var controlPropertyName = ExpressionHelper.GetPropertyName(property);
        control.DataBindings.Add(controlPropertyName, BindingSourceContext.DataSource, ObjectProperty, true);

        return this;
    }
}

public static class ExpressionHelper
{
    public static string GetPropertyName<TResult>(Expression<Func<TResult>> property)
    {
        return GetMemberNames(((LambdaExpression)property).Body).Skip(1).Join(".");
    }

    public static string GetPropertyName<T, TResult>(Expression<Func<T, TResult>> property)
    {
        return GetMemberNames(((LambdaExpression)property).Body).Join(".");
    }

    static IEnumerable<string> GetMemberNames(Expression expression)
    {
        if (expression is ConstantExpression || expression is ParameterExpression)
            yield break;

        var memberExpression = (MemberExpression)expression;

        foreach (var memberName in GetMemberNames(memberExpression.Expression))
            yield return memberName;

        yield return memberExpression.Member.Name;
    }
}

public static class StringExtentions
{
    public static string Join(this IEnumerable<string> values, string separator)
    {
        if (values == null)
            return null;

        return string.Join(separator, values.ToArray());
    }
}
publicstaticclassdatabinder
{
公共静态DataBindinderBindingSourceContext BindToObject(TDataSource数据源)
{
返回新的DataBinderBindingSourceContext(数据源);
}
}
公共类DataBinderBindingSourceContext
{
公共只读对象数据源;
公共DataBinderBindingSourceContext(对象数据源)
{
数据源=数据源;
}
公共DataBinderControlContext对象属性(表达式属性)
{
返回新的DataBinderControlContext(此,属性);
}
}
公共类DataBinderControlContext
{
只读DataBinderBindingSourceContext BindingSourceContext;
只读字符串ObjectProperty;
公共DataBinderControlContext
(
DataBinderBindingSourceContext bindingSourceContext,
表达式对象属性
)
{
BindingSourceContext=RequireAG.NotNull(BindingSourceContext);
ObjectProperty=ExpressionHelper.GetPropertyName(ObjectProperty);
}
公共DataBinderControlContext控件(TControl控件,表达式属性)
其中TControl:Control
{
var controlPropertyName=ExpressionHelper.GetPropertyName(属性);
添加(controlPropertyName,BindingSourceContext.DataSource,ObjectProperty,true);
归还这个;
}
}
公共静态类ExpressionHelper
{
公共静态字符串GetPropertyName(表达式属性)
{
返回GetMemberNames(((LambdaExpression)属性).Body.Skip(1).Join(“.”);
}
公共静态字符串GetPropertyName(表达式属性)
{
返回GetMemberNames(((LambdaExpression)属性).Body.Join(“.”);
}
静态IEnumerable GetMemberName(表达式)
{
if(表达式为常量表达式| |表达式为参数表达式)
屈服断裂;
var memberExpression=(memberExpression)表达式;
foreach(GetMemberNames(memberExpression.Expression)中的var memberName)
产生返回成员名称;
yield返回memberExpression.Member.Name;
}
}
公共静态类StringExtensions
{
公共静态字符串联接(此IEnumerable值,字符串分隔符)
{
如果(值==null)
返回null;
返回string.Join(分隔符,values.ToArray());
}
}

这不是动态绑定那么多的C语言,这是WinForms.True。即使您不使用WinForms,这种语言功能也可能派上用场。