Class.forName() equivalent in .NET?

2019-04-20 06:58发布

What is the C# way for dynamically getting the type of object and then creating new instances of it?

E.g. how do I accomplish the result of following Java code, but in C#:

MyClass x = (MyClass) Class.forName("classes.MyChildClass").newInstance();

4条回答
你好瞎i
2楼-- · 2019-04-20 07:25

Simple example:

namespace Your.Namespace
{
    public class Foo
    {
        public DateTime SixtyDaysFromNow()
        {
            return DateTime.Now + new TimeSpan(60,0,0,0);
        }
    }

    public class CreateInstance1
    {
        public static void Main(string[] args)
        {
            try
            {
                var x = Activator.CreateInstance(null, "Your.Namespace.Foo");
                Foo f = (Foo) x.Unwrap();
                Console.WriteLine("Result: {0}", f.SixtyDaysFromNow().ToString("G"));
            }
            catch (System.Exception exc1)
            {
                Console.WriteLine("Exception: {0}", exc1.ToString());
            }
        }
    }
}

Call Activator.CreateInstance() specifying an assembly name, and a classname. The classname must be fully qualified (include all the namespaces). If the assemblyname is null, then it uses the currently running assembly. If the class you want to activate is outside the currently running assembly you need to specify the assembly with the fully qualified name.

To load from a different assembly, you need to use an overload for CreateInstance that accepts a type, as opposed to a type name; one way to get a type for a given type name is to use Type.GetType(), specifying the assembly-qualified name.

Most often Activator.CreateInstance() is done using interface types, so that the instance created can be cast to the interface and you can invoke on the interface type. like this:

    interface ISixty
    {
        DateTime SixtyDaysFromNow();
    }

    public class Foo : ISixty
    {
        public DateTime SixtyDaysFromNow()
        {
            return DateTime.Now + new TimeSpan(60,0,0,0);
        }
    }

and

  var x = Activator.CreateInstance(null, "Your.Namespace.Foo");
  ISixty f = (ISixty) x.Unwrap();
  Console.WriteLine("Sixty days from now: {0}", f.SixtyDaysFromNow().ToString("G"));

Doing it that way, your app (the activating app) need not be aware of or reference the other assembly explicitly, at compile time.

查看更多
萌系小妹纸
3楼-- · 2019-04-20 07:36

Be warned about the formulation of this question. The question is "Class.forName() equivalent in .NET?" and this question is not actually answered on this page - the Class.forName() method in Java has one important side effect that the .NET equivalent does not have - that is it actually loads the class. So if you had in Java

Class c = Class.forName("mypackage.PardonMe");

You need TWO statements in C#/.NET to get the full effect:

Type t = Type.GetType("mypackage.PardonMe");
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(t.TypeHandle);

This loads the class without invoking any static methods or creating any instances.

查看更多
祖国的老花朵
4楼-- · 2019-04-20 07:37

This question has two parts

  1. How to get the Type corresponding to a name?
    Sometimes you can use Type.GetType(string). But unless the type is in mscorlib or the executing assembly you need to specify the name of the assembly in your name.

  2. How to create a given Type?
    Activatior.CreateInstance is the answer to this part.

But in your code you already know the class because you can cast to MyClass. So the question doesn't make much sense.

查看更多
爷、活的狠高调
5楼-- · 2019-04-20 07:41

Look at csharp-examples.net/reflection-examples. Basically you have to use typeof() and Activator.createInstance().

查看更多
登录 后发表回答