Хорошо, я знаю, что, возможно, я заблудился в сфере чрезмерного поведения, но мне все же хотелось бы знать, как сделать следующую работу. Я собираюсь переработать фактическое приложение, чтобы не идти на такие длины, но для будущих ссылок это кажется хорошим вопросом.Объединить два объекта, которые, как я знаю, имеют один и тот же IEnumerable <> type
Ситуация:
У меня есть ExpandoObject
, к которому я добавляю свойства, string paramName
. Все это отлично поработало, но потом я понял, что иногда я хочу иметь свойство ExpandoObject, которое является каким-то образом IEnumerable<>
, и когда я устанавливаю параметр для второго и последующих времен, я не хочу изменять сохраненный список, но я хочу чтобы объединить его.
Проблема, конечно, что IEnumerable
не имеет Add
способ. Итак, я могу просто заменить конкатенацией двух IEnumerable<>
того же типа. Я могу пожертвовать способностью использовать не-общие IEnumerables.
я чувствовал себя очень изобретательный, пока IntelliSense не запретил мне писать eo[paramName] = (eo[paramName] as IEnumerable<>).Concat(param as IEnumerable<>);
Как вы можете видеть полный код, я знаю точно, что оба param
и eo[paramName]
являются своего рода IEnumerable<>
, но я не знаю, как сказать, компилятор что я хочу, чтобы он сделал.
Любые предложения?
private void SetParam<T>(IDictionary<string, object> eo, string paramName, T param){
// eo is (ExpandoObject as IDictionary<string, object>)
var enumerableType = GetEnumerableType(typeof (T));
if (enumerableType == null)
{
// is not IEnumerable<>, but it might be not-supported IEnumerable
if (typeof (T).GetInterfaces().Contains(typeof (System.Collections.IEnumerable)))
throw new NotSupportedException("Non-generic collection types are not supported");
// it is just plain not-colection, so set value
eo[paramName] = param;
}
else
{
// first ensure that there is at least empty collection
if (eo[paramName] == null)
eo[paramName] = Activator.CreateInstance<T>();
// and concatenate
eo[paramName] = (eo[paramName] as IEnumerable<>).Concat(param as IEnumerable<>);
// or whatever other way to add param to eo[paramName]
}
}
// from: http://stackoverflow.com/a/1846690/1417905
private static Type GetEnumerableType(Type type)
{
return (from intType in type.GetInterfaces()
where intType.IsGenericType && intType.GetGenericTypeDefinition() == typeof (IEnumerable<>)
select intType.GetGenericArguments()[0]).FirstOrDefault();
}
Я не понимаю. У вас есть класс с именем ExpandoObject? Или вы просто хотите заполнить словарь? – EagleBeak
@EagleBeak ExpandoObject - это динамический класс Microsoft: https://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject%28v=vs.110%29.aspx :) – Gerino
Как насчет использования Linq: 'var result = ((IEnumerable) prm) .OfType