Get class by string value

前端 未结 5 900
感动是毒
感动是毒 2021-02-18 14:11

I have an abstract class with a few derived class

public abstract class MyObject
{
    public string name { get; set; }
    public bool IsObject(string pattern);         


        
相关标签:
5条回答
  • 2021-02-18 14:38

    It can be done using Reflection like this...

        public object getInstance(string assemblyName, string className, object[] constructorParameters)
        {
            System.Reflection.Assembly asm = System.Reflection.Assembly.Load(assemblyName);
            return asm.CreateInstance(className, false, System.Reflection.BindingFlags.CreateInstance, null, constructorParameters, null, null);
        }
    

    assemblyName - full path + assembly name

    className - fully qualified class name

    0 讨论(0)
  • 2021-02-18 14:41

    There are many good answers for your stated question. I would propose however, that you use a factory pattern for this type of requirement.

    Your 'factory' could be as simple as adding a static GetNewMyObject(string pattern) method to your base class as well as a protected static Dictionary<string, Type>. Then your derived classes could simply add their pattern + type to the factory (in a static constructor) allowing new derived classes to be added to the factory without modifying the base class.

    This way your 'pattern' strings do not have to match the type name and also you do not need to do any logical pattern matching as you can write:

    public static MyObject GetNewMyObject(string pattern)
    {
      return (MyObject)Activator.CreateInstance(StaticTypeDictionary[pattern]);
    }
    
    0 讨论(0)
  • 2021-02-18 14:44

    As Rudi Visser told, you should use reflection.

    Also to get your class name you should not hardcode it. If you whant to use your name property just write

    public abstract class MyObject
    {
        public string name 
        { 
            get
            {
                return this.GetType().Name;
            }
        }
        public bool IsObject(string pattern);
        ...
    }
    

    if you don't have the name of class, just some string that represent it, than you could check all the classes derived from MyObject

    public MyObject Create(string pattern)
    {
        Type[] types = Assembly.GetExecutingAssembly().GetTypes();
        foreach (Type type in types.Where(t => t.IsSubclassOf(typeof(MyObject))))
        {
            MyObject obj = (MyObject)Activator.CreateInstance(type);
            if (obj.name == pattern)
            {
                return obj;
            }
        }
        throw new Exception("Type " + pattern + " not found.");
    }
    
    0 讨论(0)
  • 2021-02-18 15:02

    Yes, use Reflection.

    You can use Type.GetType to get an instance of the Type for the class by string, then instantiate it using Activator.CreateInstance, something like this:

    public MyObject Create(string pattern)
    {
        Type t = Type.GetType(pattern);
        if (t == null) {
            throw new Exception("Type " + pattern + " not found.");
        }
        return Activator.CreateInstance(t);
    }
    

    You could use Activator.CreateInstance(string, string) overload also, but this would not directly return a new instance of the Type required.

    0 讨论(0)
  • 2021-02-18 15:04

    You can use Reflection or System.Activator.CreateInstance to create an instance based on the Type or TypeName as string.

    0 讨论(0)
提交回复
热议问题