获取完整的';路径';通过反射(C#)

获取完整的';路径';通过反射(C#),c#,reflection,C#,Reflection,是否有可能通过反射获得完整的“路径” 例如,假设我有以下类/属性 public class Member { public string Name; public Address Address; } public class Address { public string Line1; public string Line2; public string Line3; } 假设我有一个名为m的此类实例。是否可以通过反射,通过某种方式传递m.Addr

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

例如,假设我有以下类/属性

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

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


假设我有一个名为
m
的此类实例。是否可以通过反射,通过某种方式传递
m.Address.Line1
,以“Member.Address.Line1”(字符串)的形式获取完整路径?

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

如果是第一种情况,那么我会在我写的一篇关于CodeProject的文章中这样做,这篇文章会填充一个文本模板。代码本身有点复杂,所以我不会在这里发布,但这里有链接:

这段代码实质上分割了在每个“.”处传入的字符串,并递归地向下导航到对象树,以找到要查找的值。它还支持一些东西,如
IEnumerable
,但只支持填充模板(即,您无法导航到列表的特定索引)。

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

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

不过,您可能会有一些运气。

我假设“Address”是不存在的,正如您之前所说的,该类有三个字符串属性!第1行、第2行、第3行

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

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

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;
        }
    }

}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
命名空间控制台应用程序4
{
班级成员
{
公共字符串Line1{get;set;}
公共字符串第2行{get;set;}
公共字符串第3行{get;set;}
公共字符串名称{get;set;}
}
静态类程序
{
私有静态只读列表MyRefObjHolder=new List();
私有静态void Main()
{
成员m=新成员{Line1=“Line1”,Line2=“Line2”,Line3=“Line3”,Name=“m”};
成员n=新成员{Line1=“Line1”,Line2=“Line2”,Line3=“Line3”,Name=“n”};
新增(m);
添加(n);
字符串tmp1=GetCompleteNameWithProperty(“m.Line1”);
字符串tmp2=GetCompleteNameWithProperty(“n.Line1”);
Console.WriteLine(tmp1);//打印:Member.Line1
Console.WriteLine(tmp2);//打印:Member.Line2
Console.Read();
}
公共静态字符串GetCompleteNameWithProperty(字符串objref)
{
字符串[]obj=objref.Split('.');
如果(对象长度<2)
{
返回null;
}
字符串className=obj[obj.Length-2];
字符串propName=obj[obj.Length-1];
字符串typeName=null;
foreach(MyRefObjHolder中的对象o)
{
Type Type=o.GetType();
对象名称=type.GetProperty(“名称”).GetValue(o,null);
如果(name!=null&&name是string&&(string)name==className)
{
typeName=type.Name;
}
}
//基于linq的解决方案,使用linq one:P回复foreach循环
//字符串typeName=(从myRefObjHolder中的o选择o.GetType(),进入类型,其中type.GetProperty(propName)!=null选择type.Name);
返回typeName!=null?string.Format(“{0}.{1}”,typeName,propName):null;
}
}
}

如果您愿意使用
表达式
,那么是的,它应该很简单

就这样做吧:

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

var fullPath = GetFullPath(() => m.Address.Line1);
公共字符串GetFullPath(表达式操作){
返回action.Body.ToString();
}
var fullPath=GetFullPath(()=>m.Address.Line1);
这并不能完全满足您的需求,但它将非常接近,您可以删除不需要的部分


我将进一步深入研究该对象,看看是否有更干净的方法让您更接近您想要的内容。

您能正确发布您的类结构吗?我假设Address是IEnumerable类型的公共属性?@AppDeveloper我猜它实际上是一个包含stringthree-member类型三个成员的类,就像public string中的一样第1行{get;set;}公共字符串第2行{get;set;}公共字符串第3行{get;set;}想象一下如果您发布实际的代码?然后,其他人可以实际指导和/或为您指出正确的方向,而这可以从理论上回答问题,在这里包括答案的基本部分,并提供链接供参考。即使有链接,任何对此感兴趣的人都必须下载代码并在几乎没有任何指导的情况下搜索它。我不知道这个链接如何帮助OPI。我不认为这是OP需要的。他的问题看起来更像是“我有一个特定的变量,不知何故我想知道它属于哪个其他对象实例”。这本身并没有多大意义。格罗/DJ-是的,我能理解这种解释。。。很明显,我不是这样解释的。。我在路易斯库巴尔之前发布了我的回复,但在阅读了他的回复(以及康拉德的评论)后,我编辑了我的回复以解决这个问题。T