0

是否有可能通过反射获得完整的“路径”?

示例想象我有以下类/属性。

public class Member
{
    public string Name;
    public Address Address;
}

public class Address
{
    public string Line1;
    public string Line2;
    public string Line3;
}

想象一下,我有一个名为m. 是否有可能通过反射获得完整路径作为“Member.Address.Line1”(作为字符串),只是通过某种方式传递m.Address.Line1

4

4 回答 4

6

如果您愿意使用Expression<Func<T>>,那么是的,它应该很简单。

只需执行以下操作:

 public string GetFullPath<T>(Expression<Func<T>> action) {
  return action.Body.ToString();
}

var fullPath = GetFullPath(() => m.Address.Line1);

这并没有给你你想要的东西,但它会非常接近,你可以删除你不想要的位。

我将在该对象中再挖掘一下,看看是否有更清洁的方法可以让您更接近您想要的。

于 2012-12-28T16:55:47.540 回答
1

不。

问题是当你传递m.Address.Line1实例时,你的方法接收到的只是Line实例,它无法找出哪些实例引用了它。

当然,您可以使该方法接受类似的MyMethod(m, "Address", "Line1")内容,但这可能会破坏整个目的(很难知道,因为您没有说为什么要这样做)

不过,您可能有一些运气Expression<T>

于 2012-12-28T16:45:55.970 回答
0

我假设“地址”是不存在的,正如您之前所说的那样,该类具有三个字符串属性!1号线、2号线、3号线

我添加了一个包含类名称的额外属性“名称”,它与具有控件名称完全相同,因此我们可以根据该名称属性标记对象,

此外,如果您需要这样的输出,您必须跟踪创建的对象,因为我更喜欢 List 类型。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace ConsoleApplication4
{
    class Member
    {
        public string Line1 { get; set; }
        public string Line2 { get; set; }
        public string Line3 { get; set; }
        public string Name { get; set; }

    }

    static class Program
    {
        private static readonly List<object> MyRefObjHolder = new List<object>();

        private static void Main()
        {

            Member m = new Member {Line1 = "line1", Line2 = "line2", Line3 = "line3", Name = "m"};

            Member n = new Member {Line1 = "line1", Line2 = "line2", Line3 = "line3", Name = "n"};

            MyRefObjHolder.Add(m);
            MyRefObjHolder.Add(n);


            string tmp1 = GetCompleteNameWithProperty("m.Line1");
            string tmp2 = GetCompleteNameWithProperty("n.Line1");
            Console.WriteLine(tmp1); // prints : Member.Line1
            Console.WriteLine(tmp2); // prints : Member.Line2
            Console.Read();

        }

        public static string GetCompleteNameWithProperty(string objref)
        {

            string[] obj = objref.Split('.');

            if (obj.Length < 2)
            {
                return null;
            }

            string className = obj[obj.Length - 2];
            string propName = obj[obj.Length - 1];

            string typeName = null;
            foreach (object o in MyRefObjHolder)
            {
                Type type = o.GetType();
                object name = type.GetProperty("Name").GetValue(o, null);
                if (name != null && name is string && (string) name == className)
                {
                    typeName = type.Name;
                }

            }

            //linq based solution, replce the foreach loop with linq one :P
            //string typeName = (from o in myRefObjHolder select o.GetType() into type where type.GetProperty(propName) != null select type.Name).FirstOrDefault();


            return typeName != null ? string.Format("{0}.{1}", typeName, propName) : null;
        }
    }

}
于 2012-12-28T16:52:56.497 回答
0

首先让我确保我理解您的问题...如果您想m.Address.Line1通过将诸如“m.Address.Line1”之类的字符串传递给某个函数来获取 的值,那么是的,您可以这样做。如果您尝试从 Line1 开始并向上导航以查看哪些对象引用它,那么这是一个更难的问题,我无能为力。

如果是第一种情况,那么我在 CodeProject 上写的一篇文章中会这样做,该文章填写了一个文本模板。代码本身有点复杂,这里就不贴了,链接如下:

http://www.codeproject.com/Articles/505428/A-lightweight-recursive-text-template-data-formatt

该代码实质上拆分了您在每个“。”处传入的字符串。并递归地向下导航对象树以找到您要查找的值。它还对诸如IEnumerable但仅用于填充模板(也就是说,您不能导航到列表的特定索引)之类的东西提供了一些支持。

于 2012-12-28T16:41:52.360 回答