2013-08-25 39 views
3

我有一个类:与不同类型的工作动态

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和customClass2是完全不同的,但它们共享同一领域“dateAdded”。我希望能够调用Test1.assignData(list1,“dateAdded”)和Test1.assignData(list2,“dateAdded”)。并且list1和list2将得到更新。我怎样才能做到这一点?谢谢!

+2

做customclass1和2从customclass获得? – terrybozzio

+0

如果你真的想放弃强类型并传递属性名称来分配,那么我认为你正在寻找这样的东西:http://stackoverflow.com/questions/1089123/setting-a-property-by -reflection-a-string-value –

回答

8

要做到这一点,最好的办法是有暴露的dateAdded字段作为一个属性的通用接口,它们都实现

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

然后这两个类可以实现该接口,你可以改变的功能使用该接口

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

编辑 在评论OP表示,他们的愿望,使这个更新任何列表不管接口。在这种情况下,可能最好的办法是使用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 
    } 
    } 
} 
+0

谢谢!如果我只是想阅读它,我仍然需要实现接口?有没有办法做到这一点? – user2320462

+0

@ user2320462你总是可以使用'dynamic'或reflection来避免一个接口。一般来说,尽管我会避免它们,除非有一个令人信服的理由,并从接口 – JaredPar

+1

@ user2320462开始:您可以在您的界面中拥有一个“get”访问器。 – siride

1

如果CustomClass1CustomClass2无论从CustomClass派生并想简单地设置的targetFieldName值,所有你需要做的是与IEnumerable<T>取代List<T>

确保公共字段位于基类中,以便可以访问它而不用担心派生的实现。

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

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

有了这个,你可以调用它,因为covariance两份名单。简单的例子 -

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

List<object> list = new List<string>(); // This won't compile. 
1

所以我完全@JaredPar同意,这听起来像你需要一个通用的接口,但它是可能的动态。

注意这个例子的代码无法正常运行,如果DateAdded不存在

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); 
      } 
     } 
    } 
}