Ok, I know that I might have strayed to the realm of overcomplicating things, but I'd still like to know how to make following work. I'm going to rework actual application to don't go to such lengths, but for future reference this seems like a good question.
The situation:
I have an ExpandoObject
to which I add properties by string paramName
. It all worked great, but then I realized that sometimes I want to have an ExpandoObject property that is some kind of IEnumerable<>
, and when I set param for 2nd and subsequent times, I don't want to change the stored list, but I want to concatenate it.
The problem is, of course, that IEnumerable
doesn't have Add
method. So, I can just replace with a concatenation of two IEnumerable<>
's of the same type. I can sacrifice the ability to use non-generic IEnumerables.
I felt very ingenious until the IntelliSense disallowed me to write eo[paramName] = (eo[paramName] as IEnumerable<>).Concat(param as IEnumerable<>);
As you can see from full code, I know for sure, that both param
and eo[paramName]
are some kind of IEnumerable<>
, but I don't know how to tell compiler what I want him to do.
Any suggestions?
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();
}