Here is a highly upvoted solution to easily restrict a nested class constructor to the parent class only. I am trying to achieve exactly this but in the context of a parent class containing a nested generic class. Here is the original snippet for clarity:
public class Journal
{
private static Func<object, JournalEntry> _newJournalEntry;
public class JournalEntry
{
static JournalEntry()
{
_newJournalEntry = value => new JournalEntry(value);
}
private JournalEntry(object value)
{
...
Here is where I'm currently at (I replaced Func<object,JournalEntry>
with a simple Func<JournalEntry>
for simplicity sake.)
public class Journal
{
private static Func<JournalEntry> _new;
public JournalEntry<T> NewJournalEntry<T>()
{
return (JournalEntry<T>)_new();
}
public Journal(){}
public class JournalEntry {}
public class JournalEntry<T>:JournalEntry
{
static JournalEntry()
{
_new = () => new JournalEntry<T>();
}
private JournalEntry()
{
}
}
}
Here is the the use case:
Journal j = new Journal();
Journal.JournalEntry<string> stringEntry = j.NewJournalEntry<string>();
//Fails with null reference exception
Per this comment from the original snippet,
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor
can save the day. :)
I gave it a shot:
Journal j = new Journal();
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(Journal.JournalEntry<string>).TypeHandle);
Journal.JournalEntry<string> stringEntry = j.NewJournalEntry<string>();
//Passes
The above code works. The following works:
Journal j = new Journal();
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(Journal.JournalEntry<string>).TypeHandle);
Journal.JournalEntry<string> stringEntry = j.NewJournalEntry<string>();
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(Journal.JournalEntry<int>).TypeHandle);
Journal.JournalEntry<int> intEntry = j.NewJournalEntry<int>();
But attempting to ask for another JournalEntry<string>
fails with:
Additional information: Unable to cast object of type JournalEntry[System.Int32] to type JournalEntry[System.String].
How do I solve this dilemma such that I can make any number of instances of JournalEntry<>
with any type?