【问题标题】:How to convert variable name to string in c#.net? [duplicate]如何在 c#.net 中将变量名转换为字符串? [复制]
【发布时间】:2010-12-22 13:09:17
【问题描述】:

可能重复:
Finding the Variable Name passed to a Function in C#

public new Dictionary<string, string> Attributes { get; set; }
public string StringAttributes = string.Empty;

public int? MaxLength { get; set; }
public int? Size { get; set; }
public int? Width { get; set; }
public int? Height { get; set; }

protected override void OnInit(EventArgs e) {
    Attributes = new Dictionary<string, string>();
    Attributes.Add("MaxLength", MaxLength.ToString());
    Attributes.Add("Size", Size.ToString());
    Attributes.Add("Width", Width.ToString());
    Attributes.Add("Height", Height.ToString());
    base.OnInit(e);
}

protected override void OnPreRender(EventArgs e) {
    if (Attributes != null) {
        StringBuilder attributes = new StringBuilder();
        foreach (var item in Attributes) {
            if (!string.IsNullOrWhiteSpace(item.Value)) {
                attributes.Append(item.Key + "=\"" + item.Value + "\" ");
            }
        }
        StringAttributes = attributes.ToString();
    }
}

这里的问题是,不是使用Attributes.Add("MaxLength", MaxLength.ToString()); 并对其他属性重复相同的过程,我们是否可以不只是创建一个也能够向字典添加值的函数,其中要添加的键是它们的变量名字? 说吧,

public void addAttribute(object variable){
    Attributes = new Dictionary<string, string>();
    Attributes.Add(variable.Name, variable.Value);
}...

我想这也可能与反射有关,获取所有可为空的属性并循环遍历它们,然后将每个属性添加到字典中……但只要有其他方法,我们就不会坚持反射。

但是如果反射是唯一的选择,那么现在的另一个问题就是如何获取类的可为空属性...

任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 我不知道我们可以对此使用表达式...public string GetPropertyName(Expression&lt;Func&lt;string, string&gt;&gt; variable) { return (variable.Body as MemberExpression).Member.Name; }
  • 是的,这个问题在这里被问过不止一次。这里还有一个链接:stackoverflow.com/questions/1669016/…
  • 是的,感谢您提供的信息。 =)

标签: c# asp.net string reflection variables


【解决方案1】:

我想不出没有反思的方法。

为了获得所有可以为空的属性,您可以使用类似的代码:

GetType().GetProperties()
         .Where(property => 
          property.PropertyType.IsGenericType &&
          property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))

填充属性字典的使用示例:

PropertyInfo[] typeProperties = GetType().GetProperties();
var nullableProperties = typeProperties.Where(property => 
    property.PropertyType.IsGenericType &&
    property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>));

var attributes = new Dictionary<string, string>();
foreach (var nullableProperty in nullableProperties)
{
    object value = nullableProperty.GetValue(this,null);
    attributes.Add(nullableProperty.Name, value == null ? 
                                                string.Empty : value.ToString());
}

【讨论】:

  • 谢谢...但我现在的问题是如何获取值 foreach (var item in typeProperties){ Attributes.Add(item.Name, item.*can't get the value here*) ; }
  • 将用法示例替换为填充字典中属性的类似内容:)
  • 谢谢。我稍后会试一试。
  • 非常感谢,但我刚刚发现我们实际上不需要可为空的属性,而是需要名称包含在 字符串列表 定义的属性。这将意味着另一个 where 子句,但我不熟悉 lambda 表达式。请帮忙。谢谢。
  • GetType().GetProperties().Where(property => propertiesNames.Contains(property.Name))
【解决方案2】:

如果没有更多上下文,我不确定我是否完全理解您的问题,但也许这会有所帮助

如果关注的是多次调用的反射开销:

如果问题是通过强类型编译获取变量名,那么您可以使用

我在Oliver Hhanappi 的帖子中看到的成员类。我的blog

【讨论】:

  • 有一天我可能需要使用它。
  • 那是哪一个?我给出了 4 个可能的解决方案/想法
  • 信息缓存...但其他的也可能在某一天有用。谢谢。
【解决方案3】:

以下是我的完整解决方案。我会说你最好的选择是使用反射,因为你问的是一种元任务。至于您如何知道要添加哪些属性,我建议您定义自己的属性并将其应用于您要检查的字段/属性。

用法:

Dictionary<string, string> attributes = Inspector<MyClass>.Inspect(target);

我的示例代码中的反射在每个检查的类型中执行一次,因为它是在我的通用 Inspect 类的静态构造函数中执行的:

// apply this attribute to any properties or fields that you want added to the attributes dictionary
[AttributeUsage(
    AttributeTargets.Property |
    AttributeTargets.Field |
    AttributeTargets.Class |
    AttributeTargets.Struct |
    AttributeTargets.Interface,
    AllowMultiple = true, Inherited = true)]
public class InspectAttribute : Attribute
{
    // optionally specify the member name explicitly, for use on classes, structs, and interfaces
    public string MemberName { get; set; }

    public InspectAttribute() { }

    public InspectAttribute(string memberName)
    {
        this.MemberName = memberName;
    }
}

public class Inspector<T>
{
    // Inspector is a generic class, therefore there will be a separate instance of the _InspectActions variable per type
    private static List<Action<Dictionary<string, string>, T>> _InspectActions;

    static Inspector()
    {
        _InspectActions = new List<Action<Dictionary<string, string>, T>>();
        foreach (MemberInfo m in GetInspectableMembers(typeof(T)))
        {
            switch (m.MemberType)
            {
                case MemberTypes.Property:
                    {
                        // declare a separate variable for variable scope with anonymous delegate
                        PropertyInfo member = m as PropertyInfo;
                        // create an action delegate to add an entry to the attributes dictionary using the property name and value
                        _InspectActions.Add(
                            delegate(Dictionary<string, string> attributes, T item)
                            {
                                object value = member.GetValue(item, null);
                                attributes.Add(member.Name, (value == null) ? "[null]" : value.ToString());
                            });
                    }
                    break;
                case MemberTypes.Field:
                    {
                        // declare a separate variable for variable scope with anonymous delegate
                        FieldInfo member = m as FieldInfo;
                        // need to create a separate variable so that delegates do not share the same variable
                        // create an action delegate to add an entry to the attributes dictionary using the field name and value
                        _InspectActions.Add(
                            delegate(Dictionary<string, string> attributes, T item)
                            {
                                object value = member.GetValue(item);
                                attributes.Add(member.Name, (value == null) ? "[null]" : value.ToString());
                            });
                    }
                    break;
                default:
                    // for all other member types, do nothing
                    break;
            }
        }
    }

    private static IEnumerable<MemberInfo> GetInspectableMembers(Type t)
    {
        // get all instance fields and properties
        foreach (MemberInfo member in t.GetMembers(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.GetField | BindingFlags.GetProperty))
        {
            // check if the current member is decorated with an Inspect attribute
            object[] inspectAttributes = member.GetCustomAttributes(typeof(InspectAttribute), true);
            if (inspectAttributes != null && inspectAttributes.Length > 0)
            {
                yield return member;
            }
        }

        // now look for any Inspect attributes defined at the type level
        InspectAttribute[] typeLevelInspectAttributes = (InspectAttribute[])t.GetCustomAttributes(typeof(InspectAttribute), true);
        if (typeLevelInspectAttributes != null && typeLevelInspectAttributes.Length > 0)
        {
            foreach (InspectAttribute attribute in typeLevelInspectAttributes)
            {
                // search for members matching the name provided by the Inspect attribute
                MemberInfo[] members = t.GetMember(attribute.MemberName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.FlattenHierarchy);

                if (members != null && members.Length > 0)
                {
                    foreach (MemberInfo member in members)
                    {
                        yield return member;
                    }
                }
            }
        }
    }

    public static Dictionary<string, string> Inspect(T item)
    {
        // create a new attributes dictionary
        Dictionary<string, string> attributes = new Dictionary<string, string>();
        foreach (Action<Dictionary<string, string>, T> inspectAction in _InspectActions)
        {
            // execute each "inspect" action.
            // This will execute the delegates we created earlier, causing entries to be added to the dictionary
            inspectAction(attributes, item);
        }
        return attributes;
    }
}

public class BasePage
{
    public int? SomeValue { get; set; }
}

// example class with properties decorated with the Inspect attribute
[Inspect("SomeValue")] // also inspect the "SomeValue" property from the BasePage class
public class MyPage : BasePage
{
    [Inspect]
    public int? MaxLength { get; set; }
    [Inspect]
    public int? Size { get; set; }
    [Inspect]
    public int? Width { get; set; }
    [Inspect]
    public int? Height { get; set; }

    public string GenerateAttributeString()
    {
        System.Text.StringBuilder attributes = new System.Text.StringBuilder();
        foreach (KeyValuePair<string, string> item in Inspector<MyPage>.Inspect(this))
        {
            attributes.Append(item.Key + "=\"" + item.Value + "\" ");
        }
        return attributes.ToString();
    }
}

【讨论】:

    【解决方案4】:

    您可以使用以下函数将类中的公共 Nullable 属性提取为您要查找的格式。它还为该值调用 getter 方法。

    这与@Elisha 谈到的反射使用相同。它还对 getter 返回的值进行 .ToString() 调用。

    IDictionary<string, string> GetProps<T>(T DataObject)
    {
        if(null == DataObject)
            return new Dictionary<string, string>();
        var nullableProperties = 
            from property in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)
            from accessor in property.GetAccessors(false)
            let returnType = accessor.ReturnType
            where returnType.IsGenericType
            && returnType.GetGenericTypeDefinition() == typeof(Nullable<>)
            && accessor.GetParameters().Length == 0
            select new { Name=property.Name, Getter=accessor};
        return nullableProperties.ToDictionary(
            x => x.Name,
            x => x.Getter.Invoke(DataObject, null).ToString());
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-25
      • 1970-01-01
      • 2011-03-24
      • 1970-01-01
      • 2015-10-25
      • 1970-01-01
      • 1970-01-01
      • 2014-05-01
      相关资源
      最近更新 更多