简体   繁体   中英

Weird behavior using Activator.CreateInstance

Say I have the following class hierarchy defined in a class library:

public interface IFoo
    {
        string GetMsg();
    }

    public abstract class FooBase
    {
        public virtual string GetMsg()
        {
            return "Foobase msg";
        }
    }

    public class Foo : FooBase, IFoo
    {

        #region IFoo Members

        public new string GetMsg()
        {
            return base.GetMsg();
        }

        #endregion
    }

I'm consuming this assembly in a console application and using reflection I'm creating an instance of the Foo class typed to IFoo as follows:

 Assembly a = Assembly.LoadFile(Path.GetFullPath("TestClassLib.dll"));
 var typeDef =  a.GetType("TestClassLib.Foo");
 var fooInst = Activator.CreateInstance(typeDef) as IFoo;
 string msg = fooInst.GetMsg();

The above works fine. Now if I take this code and port it to an ASP.NET Web web page like so:

namespace TestWebApp
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            string filePath = Server.MapPath(@"~/bin/TestClassLib.dll");
            Assembly a = Assembly.LoadFile(Path.GetFullPath(filePath));
            var typeDef = a.GetType("TestClassLib.Foo");
            var fooInst = Activator.CreateInstance(typeDef) as IFoo;
            string msg = fooInst.GetMsg();
        }
    }
}

fooInst is null on the following line:

var fooInst = Activator.CreateInstance(typeDef) as IFoo;

What's interesting is when I debug the web page, I have a valid type definition in 'typeDef' variable and what is weird is that if I add Activator.CreateInstance(typeDef) as IFoo to the Watch window in Visual Studio the result is not null!

What am I missing here?

PS - I've already verified that the assembly(TestClassLib.dll) is present in the bin directory of the ASP.NET app.

My guess is that you're getting the object back from Activator.CreateInstance, but the defensive cast ("as IFoo") is failing, possibly due to load context (since you loaded the assembly with LoadFrom- see here ). Is IFoo perchance defined in both the calling assembly and the one you're loading dynamically? Maybe try letting Fusion load the assembly by doing a Type.GetType() with an assembly-qualified type name to see if you get the same result (also try storing in an object ref without the "as" to make sure CreateInstance is giving you something back).

As far as I know, you can only use as when the class/type you are casting to has a constructor. Obviously, an interface does not have a constructor. Therefore, you must box in the normal style:

var fooInst = (IFoo)Activator.CreateInstance(typeDef);

I'm pretty sure this is the case, but I could be wrong.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM