14

Is there a way to add a property to the objects of a Linq query result other than the following?

var query = from x in db.Courses
                select new
                {
                    x.OldProperty1,
                    x.OldProperty2,
                    x.OldProperty3,
                    NewProperty = true
                };

I want to do this without listing out all of the current properties of my object. There are many properties, and I don't want to have to update this code whenever I may change my class.

I am still learning with LINQ and I appreciate your suggestions.

Ronnie Overby
  • 45,287
  • 73
  • 267
  • 346

5 Answers5

8

I suppose you could return a new object composed of the new property and the selected object, like this:

var query = from x in db.Courses
                select new
                {
                    Course = x,
                    NewProperty = true
                };
Yaman
  • 1,030
  • 17
  • 33
Eric King
  • 11,594
  • 5
  • 43
  • 53
8

Add it with partial classes:

public partial class Courses
{
    public String NewProperty { get; set; }
}

Then you can assign it after you've created the object.

weiran
  • 725
  • 1
  • 8
  • 18
  • That's compile time. Isn't the question asking for run time, thus making this not a valid answer to the question? – peSHIr Feb 26 '09 at 11:11
  • 4
    Of course, if you're going to alter the original class design (to make it a partial), you might as well just go ahead and add the property... – Eric King Feb 26 '09 at 13:19
  • The class is generated by LINQ to SQL. This is the way to do it. I don't know why I didn't think to do this! I have done this before. I think it's called a brain fart. – Ronnie Overby Feb 26 '09 at 13:52
6

eking's answer will be the most straightforward approach.

If that doesn't work for you (because you need to pass the results around or whatever), and assuming the class you're dealing with already defines the property you want to set, you could create a copy constructor or factory method that takes an existing instance plus the value of the property you want to set:

var query = from x in db.Courses
            select new Course(x, valueOfNewProperty);

Alternatively, if Course doesn't define the property, you could subclass it and use the same approach:

var query = from x in db.Courses
            select new CourseWithExtraProperty(x, valueOfNewProperty);

(obviously, pick a better name for your subclass)

Again, though, unless you really need to do this, stick with eking's solution.

AwesomeTown
  • 2,800
  • 2
  • 27
  • 41
1
  • ServiceStack has a built-in way to handle this with the PopulateWith method.

    • Here's a code example.

      foreach (var item in results)
      {
          var test1 = new ItemDto().PopulateWith(item);
          test1.extraField1 = "extra";
          response.Add(test1);
      }`
      
  • And if you're not using ServiceStack, you can always use AutoMapper.

    CreateMap<Foo, Bar>().ForMember(x => x.ExtraBarProperty, opt => opt.Ignore());

Community
  • 1
  • 1
Jim G.
  • 15,141
  • 22
  • 103
  • 166
1

If you are looking to dynamically add a property to an object this could be a solution.

This is what has worked for me, I also had a concern and it was what happened with those domain objects that had many properties, the maintainability for any changes in the object was absurd, I managed to build an implementation with LINQ - ExpandObject - Reflection, which helped to keep my object dynamic and only add the additional properties that my view logic required.

var expandedModel = db.Courses.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();