如果我尝试将EntityCollection<MyNamespace.Models.MyEntityClass>
类型的对象转换为ICollection<Object>
,我会得到InvalidCastException
。
好的,根据文档,EntityCollection<TEntity>
实现了ICollection<T>
,而MyNamespace.Models.MyEntityClass
必须来自Object
,对吧?那么为什么这会失败呢?
FWIW,我正在尝试通过一种方法来执行此操作,该方法通常可以添加和删除可能是EntityCollection
或其他IList
或ISet
的内容中的项目。我需要保留EntityCollection的更改跟踪行为,因为如果它是EC,该对象最终将能够提交更改。
好的,这里有一些我正在做的具体细节。我正在反序列化JSON,并且目标对象可以具有集合的属性 - 可能它们是EntityCollection
,也许不是。为了简单起见,我们假设集合的成员总是EntityObject
的子类,无论它是EntityCollection
还是没有(如果我理解到目前为止的反应,我没有更好的运气铸造到ICollection<EntityObject>
而不是ICollection<Object>
......对吗?)。这是我遇到麻烦的部分......
foreach (PropertyInfo prop in hasManys)
{
// This is where I get the InvalidCastException...
ICollection<Object> oldHms = (ICollection<Object>)prop.GetValue(parentObj, null);
JEnumerable<JToken> hmIds = links[FormatPropName(prop.Name)].Children();
if (hmIds.Count() == 0)
{
// No members! Clear it out!
oldHms.Clear();
continue; // breaking early!
}
relType = prop.PropertyType.GetGenericArguments()[0];
// Get back the actual entities we'll need to put into the relationship...
List<EntityObject> newHms = new List<EntityObject>();
foreach (JToken jt in hmIds)
{
// ...populate newHms with existing EntityObjects from the context...
}
// first, delete any missing...
/* Got to use ToList() to make a copy, because otherwise missings is
* still connected to the oldHms collection (It's an ObjectQuery)
* and you can't modify oldHms while enumerating missings.
*/
// This cast will fail too, right? Though it's more easily fixable:
IEnumerable<EntityObject> missings = ((ICollection<EntityObject>)oldHms).Except(newHms).ToList();
foreach (EntityObject missing in missings)
{
oldHms.Remove(missing); // One of my mutable collection operations
}
// add new ones
foreach (EntityObject child in newHms)
{
if (!oldHms.Contains(child)) // Skip if already in there
{
oldHms.Add(child); // another mutable collection operation
}
}
}
}
这有点简化,我有Arrays的特殊情况(实现ICollection,但不是泛型)和我拿出的其他东西。重点是,我需要在Clear
本身上操作Add
,Remove
和EntityCollection
- 如果它就是这样的话。也许还有另一种方法来进行我缺少的这种同步?
答案 0 :(得分:1)
由于ICollection<T>
没有差异,ICollection<MyEntityClass>
和ICollection<object>
是不同的类型,彼此无关。
我正在尝试通常可以添加和删除的方法中执行此操作 来自可能是EntityCollection或其他IList或者的项目 的ISet
那么,你为什么不与IList
合作?看起来你并不关心这种方法中真实的物品类型。
答案 1 :(得分:1)
读写集合不能是变体。
举个例子:
List<MyClass> list1 = new List<MyClass>();
// assume this would work
ICollection<object> list2 = list1;
list2.Add(new object()); // ooops. We added an object to List<MyClass>!
原则上,这种类型的转换只适用于“只读”接口(允许协方差)或“只写”接口(允许相反)。
一个“解决方案”将涉及这样的包装类:
public class Wrapper<T> : ICollection<object>
{
private readonly ICollection<T> collection;
public Wrapper(ICollection<T> collection)
{
this.collection = collection;
}
public void Add(object item)
{
// maybe check if T is of the desired type
collection.Add((T)item);
}
public void Clear()
{
collection.Clear();
}
public bool Contains(object item)
{
// maybe check if T is of the desired type
return collection.Contains((T)item);
}
public void CopyTo(object[] array, int arrayIndex)
{
// maybe check if T is of the desired type
collection.CopyTo(array.Cast<T>().ToArray(), arrayIndex);
}
public int Count
{
get { return collection.Count; }
}
public bool IsReadOnly
{
get { return collection.IsReadOnly; }
}
public bool Remove(object item)
{
// maybe check if T is of the desired type
return collection.Remove((T)item);
}
public IEnumerator<object> GetEnumerator()
{
yield return collection;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return collection.GetEnumerator();
}
}
而不是
EntityCollection<MyNamespace.Models.MyEntityClass> collection = ...;
ICollection<Object> generic = collection ;
你必须写:
EntityCollection<MyNamespace.Models.MyEntityClass> collection = ...;
ICollection<Object> generic = new Wrapper(collection);
并且可以在注释标记的点处调整包装类,如何处理类型问题。