There is a base class

public abstract class Session { public abstract SessionType SessionType { get; } } 

And there is a bunch of his heirs, returning the desired type of SessionType.

Each type strictly corresponds to one heir.

Question:

How to create an instance of the desired descendant knowing the type.

PS It is clear, that it is possible to make a method on a switch creating descendants. But then each time you create a new type, you will need to add a new object initialization. Can this be done in a simpler way?

  • Somehow wrong you solve the problem. Use Type instead of SessionType or create a dictionary linking SessionType and Type. - Andrey NOP
  • Why do you need SessionType at all? Where is it used? - VladD
  • SessionType is used when processing a session, displaying data, saving related data (each type has its own data) - Andrey Tumanov

3 answers 3

As an option, you can make your own attribute through which you will establish the type SessionType between Session and SessionType :

 [AttributeUsage(AttributeTargets.Class)] public class SessionAttribute : Attribute { public SessionAttribute(Type type) { Type = type; } public Type Type { get; } } 

We decorate with our attribute SessionType :

 public class FirstSession : Session { public override SessionType SessionType => new FirstSessionType(); } public class SecondSession : Session { public override SessionType SessionType => new SecondSessionType(); } [Session(typeof(FirstSession))] public class FirstSessionType : SessionType { } [Session(typeof(SecondSession))] public class SecondSessionType : SessionType { } 

After that, you can create an instance of Session knowing SessionType :

 public static Session CreateInstanceOfSession(Type sessionType) { var attr = sessionType.GetCustomAttribute(typeof(SessionAttribute)) as SessionAttribute; if (attr != null) { return (Session)Activator.CreateInstance(attr.Type); } return null; } 

Checking:

 Console.WriteLine(CreateInstanceOfSession(typeof(FirstSessionType)).ToString()); //Выведет FirstSession Console.WriteLine(CreateInstanceOfSession(typeof(SecondSessionType)).ToString()); //Выведет SecondSession 
  • Then add an abstract property in SessionType , so it always was. - Zufir
  • @Zufir, As for me, the variant with the dictionary is even better. - trydex

Many thanks for the replies. Both answers helped me.

Solved the problem in a slightly different way, different from both proposed.

More precisely, I combined them into one solution.

Idea:

An attribute is set for each child class.

Then we scan the descendants and determine the necessary type by the attribute.

Create an instance.

Implementation:

 using System; using System.Linq; using System.Reflection; namespace TestAttrib { public enum SessionType { One , Two } public abstract class Session { public abstract SessionType SessionType { get; } public static Session construct(SessionType sessionType) { Type typeSession = typeof(Session); Type type = Assembly.GetAssembly(typeSession).GetTypes().SingleOrDefault(t => t.IsSubclassOf(typeSession) && (t.GetCustomAttribute(typeof(SessionTypeAttribute)) as SessionTypeAttribute).SessionType == sessionType ); if (type != null) { return (Session)Activator.CreateInstance(type); } return null; } } [SessionType(SessionType.One)] public class Session_One : Session { public override SessionType SessionType => SessionType.One; } [SessionType(SessionType.Two)] public class Session_Two : Session { public override SessionType SessionType => SessionType.Two; } [AttributeUsage(AttributeTargets.Class)] public class SessionTypeAttribute : Attribute { public SessionTypeAttribute(SessionType sessionType) { SessionType = sessionType; } public SessionType SessionType { get; } } class Program { static void Main(string[] args) { Console.WriteLine(Session.construct(SessionType.One).ToString()); //Выведет TestAttrib.Session_One Console.WriteLine(Session.construct(SessionType.Two).ToString()); //Выведет TestAttrib.Session_Two Console.ReadLine(); } } } 

    No, the "simpler" way to do this is impossible. But you can make it more difficult.

    You can scan all the assemblies of the process and collect all types that are non-abstract descendants of Session . Then creating an instance of each of these types and calling SessionType on it, fill in the lookup table to find the Session descendant type by the value of SessionType .

    • Can you give an example of a more complicated way? - Andrey Tumanov