【问题标题】:Extracting Method name as string from reflection or hardcoded string?从反射或硬编码字符串中提取方法名称作为字符串?
【发布时间】:2012-09-10 09:07:56
【问题描述】:

我正在从属性调用方法。我必须将属性名称作为该方法的属性传递。我的财产是

string lcl_name = string.Empty;

public string Name 
{
get { return lcl_name; }
set 
    {
        if (lcl_name != value) 
        {
            lcl_name = value;
            Foo_Method(GetCorrectPropertyName(MethodBase.GetCurrentMethod().Name));
        }
}
}

方法是

public string GetCorrectPropertyName(string propertyName)
{
    return propertyName.StartsWith("set_") || propertyName.StartsWith("get_") ? 
           propertyName.Substring(4) : string.Empty;
}

我的前辈说我不应该这样调用反射并将直接字符串传递给方法

Foo_Method("Name");

但在这种情况下,由于它是硬编码的,并且如果更改了属性名称,则必须相应地更改方法调用。

所以我的问题是,其中哪一个在效率方面会更好?有没有我的前辈看到的其他事情我没有注意到?

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    也许Expression Trees 可以在这里为您提供帮助。

    而不是Foo_Method 将属性名称作为字符串

    void Foo_Method(string name)
    {
    
    }
    

    使用Expression 类型的参数通过MemberExpression 检索属性名称:

    void Foo_Method(Expression<Func<NameOfYourClass, String>> exp)
    {
        var propertyName = ((MemberExpression)exp.Body).Member.Name;
    }
    

    然后这样称呼它

    public string Name 
    {
        get { return lcl_name; }
        set 
        {
            if (lcl_name != value) 
            {
                lcl_name = value;
                // Foo_Method("Foo"); string is bad
                Foo_Method(x => x.Name);
            }
        }   
    }
    

    这样,在重命名 Name 时,您不会破坏代码,因为 Foo_Method(x =&gt; x.Name) 也会被重命名(当然,在使用 IDE 重构功能进行重命名时)。


    编辑:

    回答您的评论:

    如果你真的不能给 Foo_Method 添加一个重载,你当然可以只创建另一个方法:

    if (lcl_name != value) 
    {
        lcl_name = value;
        Foo_Method(GetPropName(x => x.Name));
    }
    
    ...
    
    string GetPropName(Expression<Func<NameOfYourClass, String>> exp)
    {
        return ((MemberExpression)exp.Body).Member.Name;
    }
    

    编辑2:

    回答您的其他评论:

    你可以创建一个扩展方法

    public static class Extensions
    {
        public static string GetPropName<T>(this T t, Expression<Func<T, String>> exp)
        {
            return ((MemberExpression)exp.Body).Member.Name;
        }
    }
    
    var propertyName = yourInstace.GetPropName(y => y.Name);
    

    但您不必这样做,因为表达式可以在没有任何实例的情况下正常工作。

    public static class Extensions
    {
        public static string GetPropName<T>(Expression<Func<T, String>> exp)
        {
            return ((MemberExpression)exp.Body).Member.Name;
        }
    }
    
    var propertyName  = Extensions.GetPropName<YourClass>(y => y.Name);
    

    诀窍是在这里使用泛型。


    第一种方法在 VB.Net 中如下所示

    Public Function GetPropName(Of TClass, TProperty)(exp As Expression(Of Func(Of TClass, TProperty))) as String
        Return DirectCast(exp.Body, MemberExpression).Member.Name
    End Function
    
    ...
    
    GetPropName(Function(x) x.Name)
    

    【讨论】:

    • 我无法在 Foo 方法中进行更改,我的问题是关于在 Foo_method 之前应该发生什么,这就是为什么我将该方法名称命名为 Foo_method
    • 嗯,实际上您可以为Foo_Method 创建一个重载,或者创建一个完全不同的方法来使用该技术提取属性名称。
    • 无效返回。它应该是字符串。
    • 最后我有两个问题。我的GetPropName 方法是一种扩展方法。那么我怎样才能把它变成一个 EM 以便所有类都可以调用它,其次,当我在 VB.Net 中编码时,它在 VB.Net 中的等价物是什么。
    • 首先是NameOfYourClass。如果我添加一个类名。它不适用于所有人(即它不是扩展方法),其次它显示编译时错误。'System.Windows.Expression' has no type parameters and so cannot have type arguments.
    猜你喜欢
    • 1970-01-01
    • 2016-06-04
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多