如何使用LINQ动态地向对象添加属性

时间:2017-01-11 16:40:22

标签: c# linq

我有Queryable<Foo>List<Bar>。我已经能够使用LINQ映射哪些书与哪些作者相关。

我想使用Bar的值并动态地向Foo对象添加属性,如下所示,显然将类型更改为objectdynamic。< / p>

这是否可以使用LINQ,如果可以,我该怎么办?

样本所需结果(最终解析为JSON)

{
    "Id" : 1,
    "Name" : "John Doe",
    "Garden" : 7,
    "Pilot" : 4
}

示例类

public class Foo
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Bar
{
    public string Title { get; set; }
    public int Count { get; set; }
}

4 个答案:

答案 0 :(得分:2)

您无法动态地向类添加属性。我可以看到几种方法可以获得理想的结果。

最简单的方法是修改你的课程

public class Author
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Book> AuthorBooks { get; set; }
}

public class Book
{
    public string Title { get; set; }
    public string Isbn { get; set; }
}

但是这会让你的JSON结构略有不同

其他方法是使用ExpandoObject,前提是您使用的是.net.4.0或更高版本。 ExpandoObject允许您根据Dynamic类添加属性。

您可以在此处获取更多信息https://blogs.msdn.microsoft.com/csharpfaq/2009/09/30/dynamic-in-c-4-0-introducing-the-expandoobject/

希望这有助于

修改

你可以试试这样的事情

FooList.ForEach((x) =>
            {
                //Define a new expando
                dynamic NewClass = new ExpandoObject();
                NewClass.Id = x.Id;
                NewClass.Name = x.Name;
                //Get the relating Bar Record
                BarList.Where(b=> b.FooId == x.Id).ToList().ForEach((b) =>
                {
                    NewClass[b.Title] = b.Count;
                });
                //This bit Depends on how you want the Json
                using (TextWriter writer = System.IO.File.CreateText("YourFilepat/Here"))
                {
                    var serializer = new JsonSerializer();
                    serializer.Serialize(writer, NewClass);
                }

            });

JsonSerializer来自Newtonsoft.Json

答案 1 :(得分:1)

您是否尝试过使用匿名类型?

var foos = new List<Foo>{
    new Foo{Id = 1, Name = "Grapes of Wrath"},
    new Foo{Id = 2, Name = "Shantaram"}
};

var anonObject = from f in foos
                    select new
                    {
                        Id = f.Id,
                        Name = f.Name,
                        Garden = 6
                    };
var serialized = JsonConvert.SerializeObject(anonObject);
return serialized; //[{"Id":1,"Name":"Grapes of Wrath","Garden":6},
    //{"Id":2,"Name":"Shantaram","Garden":6}]

请注意,匿名类型不能跨越函数边界,因此您必须创建动态属性并在同一函数中进行序列化。

或者,您可以像这样创建新类型:

public class FooBar
{
    public Foo Foo { get; set; }
    public List<Bar> Bars { get; set; }
}

这个家伙可以随处移动,拥有你需要的所有属性,每次更改Foo或Bar时都不需要更改,并且会干净地序列化。

答案 2 :(得分:0)

使用动态属性,使用OData4中提供的“开放类型”解决了我的问题。

public IDictionary<string, object> DynamicProperties { get; set; }

通过创建DynamicProperties属性,我可以设置并获取我试图通过LINQ动态添加的成员。

Reference documentation on open types in C#

由于我没有通过LINQ解决问题,我不会选择我的答案作为接受的答案,但我认为它可能对将来的人有用。如果有人使用LINQ发布解决原始问题的答案,我会接受它。

答案 3 :(得分:0)

如果您希望向对象动态添加属性,这可能是一个解决方案。

这对我有用,我也有一个担忧,那就是那些具有许多属性的领域对象发生了什么,该对象中任何更改的可维护性都是荒谬的,我设法用 LINQ-ExpandObject-Reflection 构建实现,这有助于使对象保持动态,并且仅添加视图逻辑所需的其他属性。

var expandedModel = FooList.Select(x =>
                    {
                        dynamic expandObject = new ExpandoObject();
                        expandObject.NewProperty= $"PropertyValue";
                        foreach (var property in x.GetType().GetProperties())
                        {
                            ((IDictionary<string, object>)expandObject).Add(property.Name, property.GetValue(x));
                        }
                        return expandObject;
                    }).ToList();