-4

I have following code.

string name = GetClassName();

switch (name)
{
    case "Class1":
        new Generic<Class1>().DoSomething();
        break;
    case "Class2":
        new Generic<Class2>().DoSomething();
        break;
    case "Class3":
        new Generic<Class3>().DoSomething();
        break;
    default:
        break;
}

There might be more than 50 values of name, and seems it's not wise to have more than 50 cases. I think there must be some generic way to do that.

like

string name = GetClassName();
    
new Generic<ConverToClass(name)>().DoSomething();

Let me make my question clear. Thanks for your reply.

Actually, this code is just a snippet of my project, which is written in .NET 5.0.

I have a generic class EntityDao to CRUD entities, like Create, Update, Remove, EntityType might be User, Setting and etc. And there is a GRPC service, which accpets client request including entity type as string, entity data to CRUD entties.

class Request {
    string Type; // Entity type, which is the string of EntityType, like "User", "Setting".
    EntityAction Action; //Create, Update, Remove and etc.
    ByteString Data; // Holding entity serialized data.
}

There is also a method to handle the request from client.

Request request = GetClientRequst()

//container is IContainer of Autofac.

switch (request.Type) {
    case "User":
        container.Reslove<EntityDao<User>>().Create(request.Data); // Assuming Action is Create
        break;
    case "Setting":
        container.Reslove<EntityDao<Setting>>().Create(request.Data); // Assuming Action is Create
        break;
    case "Other": // Have more than 50 entity types.
        break;
}
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
Ares Zhu
  • 55
  • 6
  • What exactly are you trying to archive here? Create new instance, call the method and dispose it immediate? What is the core system this is supposed for? This sounds like a XY problem – X39 Jan 25 '21 at 00:46
  • Thanks for your reply, I have updated my question, hope it can make it clear. – Ares Zhu Jan 25 '21 at 01:01
  • I can't really tell what you are doing (what's the role of `GetClassName`). But take a look at reflection. Given a class name, you can get a type. Then you can compose a generic type, and the get a function on that type by name, and invoke it. – Flydog57 Jan 25 '21 at 01:03
  • 1
    Use [`Activator.CreateInstance`](https://learn.microsoft.com/en-us/dotnet/api/system.activator.createinstance?view=net-5.0) – Charlieface Jan 25 '21 at 01:13
  • 3
    Does this answer your question? [Create object instance of a class having its name in string variable](https://stackoverflow.com/questions/15449800/create-object-instance-of-a-class-having-its-name-in-string-variable) – Charlieface Jan 25 '21 at 01:14

1 Answers1

2

Take a look at Type.GetType(string):

string name = GetClassName();

Type klass = Type.GetType("Namespace." + name); // Replace "Namespace." with all the namespaces the classes live in, as the argument to `Type.GetType()` should be a fully-qualified name
if (klass is null)
{
    // Class was not found
}

Of course, you also need to create an instance of Generic<klass>:

Type genericOfKlass = typeof(Generic<>).MakeGenericType(klass);

Then instantiate it:

object instance = Activator.CreateInstance(genericOfKlass);

Then call .DoSomething() on it:

MethodInfo doSomething = genericOfKlass.GetMethod("DoSomething", BindingFlags.Public | BindingFlags.Instance);
doSomething.Invoke(instance, new object[] { });

As you can see, reflection (this kind of dynamic programming is called reflection) is not easy, but possible in .NET.

Edit: Complete example with request data:

Request request = GetClientRequst();

//container is IContainer of Autofac.

Type requestType = Type.GetType("Namespace." + requestType); // Replace "Namespace." with all the namespaces the classes live in, as the argument to `Type.GetType()` should be a fully-qualified name
Type entityDao = typeof(EntityDao<>).MakeGenericType(requestType);
MethodInfo containerResolve = container.GetType().GetMethod("Resolve");
MethodInfo genericContainerResolve = containerResolve.MakeGenericMethod(entityDao);
object resolveResult = genericContainerResolve.Invoke(container, new object[] { });
MethodInfo create = resolveResult.GetType().GetMethod("Create");
create.Invoke(resolveResult, new object[] { request.Data });
Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77