是否有可能获得完整的路径'通过反思?
示例假设我有以下类/属性。
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
?
答案 0 :(得分:4)
如果您愿意使用Expression<Func<T>>
,那么是的,应该很简单。
做这样的事情:
public string GetFullPath<T>(Expression<Func<T>> action) {
return action.Body.ToString();
}
var fullPath = GetFullPath(() => m.Address.Line1);
这并不能完全满足您的需求,但它会非常接近,您可以删除不想要的位。
我会在那个对象中挖掘一下,看看是否有更清洁的方法让你更接近你想要的东西。
答案 1 :(得分:1)
没有
问题在于,当您传递m.Address.Line1
实例时,您收到的所有方法都是Line
实例,并且无法找出哪些实例引用它。
当然,你可以让这个方法接受像MyMethod(m, "Address", "Line1")
这样的东西,但这可能会破坏整个目的(很难知道,因为你没有说明你为什么要这样做)
你可能会对Expression<T>
感到幸运。
答案 2 :(得分:0)
让我首先确保我理解你的问题......如果你想通过将一个字符串如“m.Address.Line1”传递给某个函数来获取m.Address.Line1
的值,那么是的,你可以做那。如果您尝试从Line1开始并向上导航树以查看哪些对象引用它,那么这是一个更难的问题,我无法帮助。
如果是第一种情况,那么我在CodeProject上写的一篇文章中填写文本模板。代码本身有点复杂,所以我不会在这里发布,但这里是链接:
http://www.codeproject.com/Articles/505428/A-lightweight-recursive-text-template-data-formatt
代码本质上会拆分你在每个“。”传入的字符串。并递归地向下导航对象树以找到您要查找的值。它还支持IEnumerable
之类的内容,但仅用于填写模板(即,无法导航到列表的特定索引)。
答案 3 :(得分:0)
我假设“地址”是不存在的东西,因为早先你说过Class有三个字符串属性! Line1,Line2,Line3
我添加了一个额外的属性“Name”,它保存了类的名称,它与控件名称完全相同,因此我们可以根据Name属性标记对象,
另外,如果你需要这样的输出,你必须跟踪创建的对象,为此我更喜欢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;
}
}
}