3

I have a class:

 public class Test1
 {
     public void assignData(List<CustomClass> customData, string targetFieldName)
     {             
         for(int i=0; i<customData.Count; i++)
         {
             if(customData[i].targetFieldName)
             {
                 customData[i].targetFieldName = newValue;
             }   
         }
     }
 }

 List<customClass1> list1;
 List<customClass2> list2;

customClass1 and customClass2 are completely different, but they share the same field 'dateAdded'. I want to be able to call Test1.assignData(list1, "dateAdded") and Test1.assignData(list2, "dateAdded"). and the list1 and list2 will get updated. How can I do that? Thanks!

Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
user2320462
  • 259
  • 3
  • 9
  • 2
    do customclass1 and 2 derive from customclass ? – terrybozzio Aug 25 '13 at 16:08
  • If you really want to let go of strong typing and pass a property name to assign, then I think you're looking for something like this: http://stackoverflow.com/questions/1089123/setting-a-property-by-reflection-with-a-string-value – Mathieu Guindon Aug 25 '13 at 16:54

3 Answers3

8

The best way to do this is to have a common interface that they both implement which exposes the dateAdded field as a property

interface ICustomClass {
  DateTime dateAdded { get; set; }
}

Then both classes can implement that interface and you can change the function to use that interface

public void assignData(IEnumerable<ICustomClass> enumerable) {
  foreach (var customData in enumerable) {
    customData.dateAdded = newValue;
  }
}

EDIT In the comments the OP stated their desire to make this update to any list irrespective of the interface. In that case the likely best course is to use dynamic

public void assignData(IEnumerable<object> enumerable) {
  foreach (dynamic customData in enumerable) {
    try { 
      customData.dateAdded = newValue;
    } catch { 
      // Object doesn't have dateAdded so just move on
    }
  }
}
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • Thanks! What if I just want to read it I still have to implement the interface? is there a way of doing it without? – user2320462 Aug 25 '13 at 16:14
  • @user2320462 you can always use `dynamic` or reflection to avoid an interface. In general though I would avoid them unless there was a compelling reason and start with an interface – JaredPar Aug 25 '13 at 16:18
  • 1
    @user2320462: you can just have a `get` accessor in your interface. – siride Aug 25 '13 at 16:33
  • @JaredPar I want to be able to alter any list, so that I don't have to make any adjustments to target list class, just any list that has dateAdded field in it, should be updated – user2320462 Aug 25 '13 at 16:57
  • @user2320462 then your best choice in that case is to use `dynamic`. I'll update with a sample – JaredPar Aug 25 '13 at 16:58
  • 1
    Where is `newValue` coming from - missing parameter? – Derek W Aug 25 '13 at 17:09
  • 1
    @DerekW unknown, the original question just has `newValue` without any context. I just assumed it was a field the OP omitted from the question – JaredPar Aug 25 '13 at 17:11
1

If CustomClass1 and CustomClass2both deriving from CustomClass and you want to simply set value of targetFieldName , all you need to do is replace List<T> with IEnumerable<T>.

Make sure the common field is in base class so that it can be accessed without worrying about the derived implementation.

public void assignData(List<CustomClass> customData, string targetFieldName)

with

public void assignData(IEnumerable<CustomClass> customData,
                                                string targetFieldName)

With this you can call it for both lists because of covariance. Simple example -

IEnumerable<object> list = new List<string>(); // This will work

List<object> list = new List<string>(); // This won't compile.
Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
1

So I totally agree with @JaredPar that this sounds like you need a common interface but it is possible with dynamics.

Note that this example code doesn't behave properly if DateAdded isn't present

using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;

namespace dynamics_test
{
    class CustomOne
    {
        public string NotInCustomTwo { get; set; }
        public DateTime DateAdded { get; set; }
    }

    class CustomTwo
    {
        public string NotInCustomOne { get; set; }
        public DateTime DateAdded { get; set; }
    }


    [TestFixture]
    public class TestDynamics
    {
        private List<CustomOne> _customOnes;
        private List<CustomTwo> _customTwos;

        [SetUp]
        public void Setup()
        {
            this._customOnes = new List<CustomOne>()
                {
                    new CustomOne {DateAdded = DateTime.Now.AddDays(1), NotInCustomTwo = "some value"},
                    new CustomOne {DateAdded = DateTime.Now, NotInCustomTwo = "some value"}
                };
            this._customTwos = new List<CustomTwo>()
                {
                    new CustomTwo {DateAdded = DateTime.Now.AddDays(1), NotInCustomOne = "some value"},
                    new CustomTwo {DateAdded = DateTime.Now, NotInCustomOne = "some value"}
                };
        }

        [Test]
        public void DynamicsAllowBadThingsMkay()
        {
            var dynamics = _customOnes.Cast<dynamic>().ToList();
            dynamics.AddRange(_customTwos);
            Assert.AreEqual(2, dynamics.Count(d=>d.DateAdded.Date == DateTime.Now.Date));
            foreach (var thing in dynamics)
            {
                Console.WriteLine(thing.DateAdded);
            }
        }
    }
}
Paul D'Ambra
  • 7,629
  • 3
  • 51
  • 96