是否有可能通过反射来获取完整的“路径”?
例如想象我有下面的类/属性。
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
?
如果你愿意使用Expression<Func<T>>
那么是的,它应该是简单的。
只是这样做:
public string GetFullPath<T>(Expression<Func<T>> action) {
return action.Body.ToString();
}
var fullPath = GetFullPath(() => m.Address.Line1);
这不给你你想要什么,但它会很接近,你可以删除你不想要的位。
我将在该对象多一点挖过来,看看是否有一个更清洁的方式来让你更接近你想要什么。
没有。
问题是,当你通过m.Address.Line1
情况下,所有的方法接收是Line
的实例,它有没有办法找出哪些实例引用它。
你当然可以,使该方法接受类似MyMethod(m, "Address", "Line1")
但是这可能会毁掉整个目的(很难知道,因为你没有说你为什么想要这个)
你可能有一些运气Expression<T>
虽然。
首先,我要确保我明白你的问题...如果你想获得的价值m.Address.Line1
通过传递一个字符串,如“m.Address.Line1”一些功能,然后是你可以做到这一点。 如果你想开始与1号线和导航上树,看看对象引用它,那么这是一个非常困难的问题,我也没有办法。
如果是第一种情况,那么我这样做的一篇文章我在CodeProject上写了一个文本模板逐渐填满。 代码本身是有点复杂,所以我不会张贴在这里,但这里的链接:
http://www.codeproject.com/Articles/505428/A-lightweight-recursive-text-template-data-formatt
该代码基本上拆分您在每个传递字符串“” 和递归向下导航对象树以找到您正在寻找的价值。 它也有东西像一些支持IEnumerable
,但只在模板填充(也就是不能导航到列表中的一个特定的指数)。
我假设“Address”就是那不存在的,正如前面你说的那个类有三个字符串属性的东西! 1号线,2号线,3号线
我已经添加了一个额外属性“名称”持有类的名称,具有控制名称,所以我们可以对Name属性的基础上标记对象的不太一样,
此外,如果你需要这样的输出u必须跟踪创建的对象的,对于我宁愿一个列表类型。
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;
}
}
}