简体   繁体   English

引用c#Object Field作为字符串传递的名称

[英]Reference an c# Object Field by its name passed as a string

I am writing a custom repoting module using ASP.NET MVC in C# 我在C#中使用ASP.NET MVC编写自定义报表模块

The user will be able to define a list of the fields they want to see in the report. 用户将能够定义他们想要在报告中看到的字段列表。

I would like to know if it is possible to reference a object field using a string, so that I can enumerate through the list of chosen fields. 我想知道是否可以使用字符串引用对象字段,以便我可以枚举所选字段的列表。

for example normally in the view, quite basically I would do the following 例如,通常在视图中,基本上我会做以下事情

@foreach (Title item in Model)
{
    @item.Name 
    @item.Isbn
}

I would be looking for something like 我会寻找类似的东西

@foreach (Title item in Model)
{
    @item.Select("Name")
    @item.Select("Isbn")
}

One of the ways to do that is through reflection. 其中一种方法是通过反思。 Add this helper method somewhere: 在某处添加此辅助方法:

private object GetValueByPropertyName<T>(T obj, string propertyName)
{
    PropertyInfo propInfo = typeof(T).GetProperty(propertyName);

    return propInfo.GetValue(obj);
}

Usage: 用法:

@foreach (Title item in Model)
{
    var name =  GetValueByPropertyName(item, "Name");
    var isbn =  GetValueByPropertyName(item, "Isbn");
}

I'm not experienced with asp, so I don't know for sure if this is possible in your specific context. 我对asp没有经验,所以我不确定这是否可以在您的特定环境中使用。

But normally you could use reflection for that. 但通常你可以使用反射。 But you had to know if you are looking for properties or fields 但你必须知道你是在寻找属性还是字段

For fields: 对于字段:

FieldInfo fi = item.GetType().GetField("Name", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
var value = fi.GetValue(item); // read a field
fi.SetValue(item, value); // set a field

For properties: 对于属性:

PropertyInfo pi = item.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
var value = pi.GetValue(item); // read a property
pi.SetValue(item, value); // set a property

The word to google for is "Reflection" and most methods can be found in the Type class. google for这个词是“Reflection”,大多数方法都可以在Type类中找到。

Well, i'd strongly recommend against using reflection in View as it breaks main principles of MVC pattern. 好吧,我强烈建议不要在View 使用反射,因为它打破了MVC模式的主要原则。 YES, you should use reflection, but it is better to use it in controller. 是的,你应该使用反射,但最好在控制器中使用它。 Let's have a look at simple and working example. 让我们来看看简单而有效的例子。

In controller we set up stub data to work with. 在控制器中,我们设置了要使用的存根数据。 And in action method About() we obtain a dynamic list of properties that user has selected : 在操作方法About()中,我们获取用户选择的动态属性列表:

class Title
{
    // ctor that generates stub data 
    public Title()
    {
        Func<string> f = () => new string(Guid.NewGuid().ToString().Take(5).ToArray());
        A = "A : " + f();
        B = "B : " + f();
        C = "C : " + f();
        D = "D : " + f();
    }

    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }
    public string D { get; set; }
}

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult About()
    {
        var data = new List<Title>()
        {
            new Title(), new Title(),
            new Title(), new Title()
        };

        // list of properties to display for user
        var fieldsSelectedByUser = new[] { "A", "C" };

        // here we obtain a list of propertyinfos from Title class, that user requested
        var propsInfo = typeof(Title).GetProperties().Where(p => fieldsSelectedByUser.Any(z => z == p.Name)).ToList();

        // query that returns list of properties in List<List<object>> format
        var result = data.Select(t => propsInfo.Select(pi => pi.GetValue(t, null)).ToList()).ToList();

        return View(result);
    }

    ...
}

And in view we can use it by simply iterating the collection : 在视图中我们可以通过简单地迭代集合来使用它:

@model List<List<object>>

<br/><br />

@foreach (var list in @Model)
{
    foreach (var property in list)
    {
        <p> @property&nbsp;&nbsp;</p>
    }

    <br/><br />
}

PS PS

According to MVC pattern, view should utilize data returned by controller but should at no circumstances perform any business logic and comprehensive operations inside of it. 根据MVC模式,视图应该利用控制器返回的数据,但在任何情况下都不应该在其中执行任何业务逻辑和综合操作。 If view need some data in some format - it should get this data returned by controller exactly in the format it needs. 如果视图需要某种格式的某些数据 - 它应该以控制器所需的格式获取控制器返回的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM