Reputation: 1045
.NET 4.0
introduced a non-generic IList
which exposes the ability to add values to the List without needing to know the generic type. This is useful because it allows me to write a method such as the following:
void CreateListFromBytes(IntPtr bytes, Type outputType, out object outputObject)
{
Type elementType = outputType.GenericTypeArguments[0];
int numberOfElements = ReadHeaderBytes(bytes);
bytes += Marshal.SizeOf(typeof(int));
IList outputList = (IList) Activator.CreateInstance(outputType);
for (int i = 0; i < numberOfElements; i++)
{
object element = ReadDataBytes(bytes, elementType);
bytes += Marshal.SizeOf(elementType);
outputList.Add(element);
}
outputObject = outputList;
}
However, when I try to implement a method with a similar style for HashSet
or ISet
, there is not such non-generic interface I can find that exposes and Add()
method.
I am wondering if such an interface exists that I may have missed. If not, I am wondering how I can go about adding elements to object I know for certain is Set
(since I created it the Activator.CreateInstance()
)
Upvotes: 2
Views: 990
Reputation: 9214
I would end up with a couple of aux types for constructing a set:
interface ISetBuilder
{
void Add(object item);
object Build();
}
class SetBuilder<T, TSet> : ISetBuilder where TSet : ISet<T>, new()
{
private readonly TSet _set = new TSet();
public void Add(object item)
{
if (!(item is T typedItem))
{
throw new ArgumentException();
}
_set.Add(typedItem);
}
public object Build() => _set;
}
Those types then could be used like this:
var builderType = typeof(SetBuilder<,>).MakeGenericType(elementType, outputType);
var builder = (ISetBuilder) Activator.CreateInstance(builderType);
var element = CreateElement(...);
builder.Add(element);
var set = builder.Build();
And yes, this could be generalised to support lists as well. Just replace ISet<T>
with ICollection<T>
.
Another possible (but a bit less robust) solution is just to find and call the specific Add
method of a set by using reflection.
Upvotes: 1