C
C#•2y ago
RazorSharpFang

How do you pass into a method a generic after you've reflected? [Answered]

Suppose I suspect that this IEnumerable (non-generic) is also an IReadOnlyList<T> where T : struct. Unfortunately due to the rules of casting, an IReadOnlyList<T> where T : struct is not castable to an IReadOnlyList<object> How unfortunate! But we have reflection! Suppose I have an IEnumerable called source. I can probe its types as follows
// source is of type System.Collections.IEnumerable
var type = source.GetType();
var interfaces = type.GetInterfaces();
for (int i = 0; i < interfaces.Length; i++)
{
var @interface = interfaces[i];
if (@interface is null)
continue;
// null check satisifed
if(@interface.GenericTypeArguments.Length == 1 && @interface.GetGenericTypeDefinition() == typeof(IReadOnlyList<>))
{
// found it. It is in fact an IReadOnlyList<T> where T : struct
// but now what? Can I get a strongly typed reference to an IReadOnlyList<T> where T : struct ?
}
}
// source is of type System.Collections.IEnumerable
var type = source.GetType();
var interfaces = type.GetInterfaces();
for (int i = 0; i < interfaces.Length; i++)
{
var @interface = interfaces[i];
if (@interface is null)
continue;
// null check satisifed
if(@interface.GenericTypeArguments.Length == 1 && @interface.GetGenericTypeDefinition() == typeof(IReadOnlyList<>))
{
// found it. It is in fact an IReadOnlyList<T> where T : struct
// but now what? Can I get a strongly typed reference to an IReadOnlyList<T> where T : struct ?
}
}
Another class takes in as an argument to its constructor, IReadOnlyList<T> Defined below:
public ReadOnlyListWrapper(IReadOnlyList<T> backingList) { /* BODY HERE */ }
public ReadOnlyListWrapper(IReadOnlyList<T> backingList) { /* BODY HERE */ }
How do I after probing call this constructor now that I know it implements the interface as required?
24 Replies
Kai
Kai•2y ago
Is there a reason you need to do this via reflection? I think you can just do
if (source is IReadOnlyList<T> list)
if (source is IReadOnlyList<T> list)
though for that you need a T given somehow. If that's not possible, you can do
var instance = Activator.CreateInstance(typeof(ReadOnlyListWrapper<>).MakeGenericType(@interface.GenericTypeArguments.Single()), source);
var instance = Activator.CreateInstance(typeof(ReadOnlyListWrapper<>).MakeGenericType(@interface.GenericTypeArguments.Single()), source);
But if it's at all possible for you I'd strongly recommend just handing through the generic argument several times, instead of loosing the type somewhere and then restoring it in this way
RazorSharpFang
RazorSharpFang•2y ago
I do not have T known.
Kai
Kai•2y ago
In that case the second solution should work. Not very pretty and you loose a bunch of type safety (you also get back an object, so...)
RazorSharpFang
RazorSharpFang•2y ago
Oh so I do. Yeah I agree that this isn't pretty, but this is already the backwards-compat slow code-path anyway
Kai
Kai•2y ago
fair enough 😛
RazorSharpFang
RazorSharpFang•2y ago
Related to AvaloniaUI PR 8764 if you're interested https://github.com/AvaloniaUI/Avalonia/issues/8764
GitHub
For Avalonia.Controls.ListBox for Items Property, Support for IRead...
Describe the bug For a DataContext View-Model that has Specialized Collections, collections may implement the IList&lt;T&gt; or IReadOnlyList&lt;T&gt; interfaces, neither of which i...
RazorSharpFang
RazorSharpFang•2y ago
About collections that don't implement non-generic IList Hence all of the weird casting going on Remember that IList (non-generic) and IReadOnlyList<T> have nothing in common outside of IEnumerable
Kai
Kai•2y ago
IEnumerable should just not exist in modern .NET but yeah legacy code... Also I don't really understand your issue. Imo it doesn't make sense to ever have a type that implements IReadOnlyList<T> and INotifyCollectionChanged but not some kind of IList(<T>) Given INotifyCollectionChanged only makes sense if the collection can actually change, but IReadOnlyList<T> explicitly can't change Like, in what case would the event fire?
RazorSharpFang
RazorSharpFang•2y ago
My point is that IList<T> extends IReadOnlyList<T> Supporting a viewer that works with IReadOnlyList<T> by definition must work with IList<T> Presuming that the interface contract is implemented correctly
Kai
Kai•2y ago
due to legacy reasons that 's not true though IList<T> does not extend IReadOnlyList<T>
RazorSharpFang
RazorSharpFang•2y ago
👀
Kai
Kai•2y ago
yup.... IList<T> is .NET FX 2.0 and IReadOnlyList<T> is .NET FX 4.5 :/
RazorSharpFang
RazorSharpFang•2y ago
Oh and here I thought ICollection<T> : IReadOnlyList<T> What on earth are these interface angryowo
Kai
Kai•2y ago
✨ legacy code ✨
RazorSharpFang
RazorSharpFang•2y ago
And you have a whole bunch of classes that implement IList but don't implement IReadOnlyList<T> now?
Kai
Kai•2y ago
not really I mean .NET types all implement both iirc it's just the rare externally implemented collection type might be weird now Do you actually have a type that implements IReadOnlyList<T> and INotifyCollectionChanged, but not IList(<T>)????
RazorSharpFang
RazorSharpFang•2y ago
It implements IList<T> But not non-generic IList I was under the impression that IList<T> : IReadOnlyList<T> But that is clearly wrong.
Kai
Kai•2y ago
oh that is actually somewhat reasonable and imo an oversight in avalonia
RazorSharpFang
RazorSharpFang•2y ago
Ah, but maxkatz6 says by-design. Perhaps they thought I knew that IList<T> does not extend IReadOnlyList<T> I am not so competent, clearly.
Kai
Kai•2y ago
I think the part of your issue that says IReadOnlyList<T> is by-design, but that it doesn't support IList<T> is a valid problem imo can't imagine they disregard that too as by-design 🤔
RazorSharpFang
RazorSharpFang•2y ago
Okay but I feel like it would weird to close this one and then immediately raise a new issue about not supporting IList<T>
Kai
Kai•2y ago
looks like they are fine just discussing it as is?
RazorSharpFang
RazorSharpFang•2y ago
Yeah, maybe I'm just overreacting to the label change
Accord
Accord•2y ago
✅ This post has been marked as answered!
Want results from more Discord servers?
Add your server
More Posts
Signalr not sending message(s) to specific user(s)in the hub i have setup this signature for a method ```cs public async Task SendMessage(string sendRider line problemI'd moved to rider but a line make me angry, anybody can help me about how can I remove this?Is it possible to publish a WPF Application into a single file with the font inside of the EXE?Is it possible to publish a WPF Application into a single file with the font inside of the EXE?Binding to Dictionary in WPF with a binding KEYhello i have a very specific problem related to WPF : i have a listbox with itemsSource <ListBox Itset default value of parameter to other parameter [Answered]ok, i am aware that this is probably not possible, but can i set default value of parameter x to vaChecking if an arbitrary (remote) URL is a file attachment, and extracting it if it is? [Answered]If I'm given an arbitrary URL (I don't have control over it), how can I check if it appears to be a How does assigning default values when creating an instance work? [Answered]I'm not sure how to ask this question. I also can't for the life of me remember what this style of iProcess.EnableRaisingEvents does not work on WindowsI have an app that have 20 workers that are other processes. On production, on ubuntu, when I close Top-level statements in MSVSSay you've created a new project with top-level statements in MSVS. Is it possible to change it to *how to format multiple conditions assignments in return statement [CLOSED] [Answered]Greetings, I was wondering, how could I properly format this piece of code. ```cs return res > Pag