在运行时之前未知列表类型时添加到列表

时间:2014-04-10 02:58:16

标签: c# generics

我有接受object的方法。我知道这个对象是List<T>但是当传递给方法时,任何时候基类的子节点之间的T都可能不同。

因此,如果我的基类是MonthType,并且我有一个名为BlockMonthTypeAreaMonthType的子项,则传入的对象可以是List<BlockMonthType> or List<AreaMonthType>中的任何一个。

我希望能够向此对象添加项目,但是当我投射它时,它似乎会复制并且原始对象不会更新。

我这样做是为了施展:

var objectList = ((IEnumerable<MonthType>)graphObject.Source.Object).ToList();

现在我想创建一个新项目并将其添加到列表中

// where ObjectType is a Type variable containing BlockMonthType
var newObject = (BlockMonthType)Activator.CreateInstance(graphObject.Source.ObjectType);

objectList.Add(newObject);

// and carry on the world is good

只要objectList添加了newObject,这就可以工作。但是原始变量没有更新,所以当我离开方法时它会恢复到它的原始状态。我知道对象是List&lt;&gt;传入时,因为我可以在调试器中看到它。

无论如何我能做到这一点吗?

以下是我正在使用它的方法的缩减版本。

public TraverseGraphResult Write(ObjectGraph graphObject)
{
    var objectList = ((IEnumerable<MonthType>)graphObject.Source.Object).ToList();

    var newObject = (MonthType)Activator.CreateInstance(rule.ObjectType);
    newObject.Month = rule.Month;

    objectList.Add(newObject);

    // Other stuff as well is done but that's the crux of it
}

希望这能为它提供更多背景信息。该方法用于尝试和导航具有许多类类型的大对象树。我正在尝试添加一个新的类类型处理程序,它将处理从列表中添加和删除项目。

// This is being used in a recursive method to loop down a object's property tree

// .. more code here

// where properties is a List<PropertyInfo>
foreach (var pInfo in properties)
{
    if (IsList(pInfo.PropertyType))
    {
        var enumerable = (IEnumerable)pInfo.GetValue(currentObjectGraph.Source.Object, null);

        var sourceEnumerator = enumerable.GetEnumerator();          
        var graph = new ObjectGraph(enumerable, pInfo.Name);

        // this part is made up but essentially the code looks up a list of objects that can deal with this 
        // particular one and returns it.  We then call the write method on that object
        var something = GetInterfaceHandlerForObject(enumerable);
        something.Write(graph);
    }
}

2 个答案:

答案 0 :(得分:4)

你应该使你的方法通用:

public void MyMethod<T>(List<T> objectList) where T:class, new()
{
    objectList.Add(new T());
    ...
}

使用泛型时很少需要进行强制转换。此外,您的ToList()正在创建列表的新副本。

这种方法的一个缺点是T需要一个空的构造函数。如果需要使用参数构造对象,则可以传入Func<T>。然后,您可以调用它传递lambda表达式,如:(x) => new BlockMonthType(someParameter, orAnother)

答案 1 :(得分:0)

我最终通过将基础List T类型存储在ObjectGraph对象中并在需要时强制转换为此来解析此问题。

var objectList = ((IEnumerable)graphObject.Source.Object).Cast(monthAllocationRule.ListType);

没有正确的强制转换对象列表为null或列表的副本。现在我可以添加到objectList并知道它已添加到源对象。

可能不是像上面提到的Ian那样的想法,而是诀窍。