具有动态类型的Activator.CreateInstance

时间:2014-04-16 09:27:52

标签: c#

我认为我缺乏理解,到底发生了什么: 用户可以输入程序集的路径和对象类型,然后尝试创建它的实例。

我的方法:

        Assembly a = Assembly.LoadFile(txtAssemblyPath.Text);
        Type myType = a.GetTypes().ToList().FirstOrDefault(f => f.Name == txtObjectName.Text);

        var obj = Activator.CreateInstance<myType>();
        var obj2 =(myType) Activator.CreateInstance(myType);

问题在于创建对象本身。似乎myType没有作为Type进行威胁。在此示例中:Creating generic variables from a type - How? Or use Activator.CreateInstance() with properties { } instead of parameters ( )?

他们只是得到一个对象,所以我猜这不是同一个案例。我根本不理解:CreateInstance(Type)有效,但Type的CreateInstance没有,但T和Type应该相同:System.Type。

提前感谢澄清。

的Matthias

3 个答案:

答案 0 :(得分:3)

有一个使用差异......当你写:

var obj = Activator.CreateInstance<myType>();

你像班级一样使用你的班级,这是做这件事的好方法。 您使用了一个引用类类型的泛型类型。

但是那里:

var obj2 =(myType) Activator.CreateInstance(myType);

您使用的类就像一个实例(对象)。你不能这样做,一个类是一个模式。 如果要调用第二种方法,则必须写:

var obj2 =(myType) Activator.CreateInstance(typeof(myType));

此代码将创建类Type的实例,此实例将描述您的类myType。

我希望能够清楚。

一个类是一个模式,你可以用这个模式创建一个对象,它将是一个实例(你的类的一个内存对象)。

答案 1 :(得分:2)

当您使用泛型类型的方法(例如Activator.CreateInstance<T>();)时,您必须提供T的强类型。这意味着您必须传递已知类型名称而不是T.例如:< / p>

var activatorPerson = (Person)Activator.CreateInstance<Person>();

这就是Activator.CreateInstance(typeGoesHere)函数的非泛型的原因,可用于我们没有强类型的情况在创建对象的那一刻。所以我们可以将type作为参数传递给该函数。我们可以通过多种方式提供类型变量。在您的情况下,您可以在程序集中找到正确的类型:

Type myType = a.GetTypes().ToList().FirstOrDefault(f => f.Name == txtObjectName.Text);

您还必须注意,在您的代码中键入的显式转换无效:

obj2 =(myType) Activator.CreateInstance(myType);

因为您必须为显式转换提供强类型名称。 当我们在运行时无法访问强类型名称时,我们必须使用非泛型版本的方法。

答案 2 :(得分:0)

这是纯粹的动态方式。

这是工厂类和动态实例创建方法:

    public class RepositoryFactory
{
    public static dynamic CreateDynamic<TEntity>() where TEntity : BaseEntity
    {
        dynamic repositoryInstance = null;
        var subRepositories = AssemblyHelper.GetSubclassesOf(typeof(BaseRepository<TEntity>), true);
        var entityTypeName = typeof(TEntity).Name;
        var subRepository = subRepositories.FirstOrDefault(x => x.Name == entityTypeName + "Repository");
        if (subRepository != null)
        {
            var repositoryType = subRepository.UnderlyingSystemType;
            repositoryInstance = Activator.CreateInstance(repositoryType);
        }
        return repositoryInstance;
    }
}

这是实体和存储库之间映射类型的辅助类。

public static class AssemblyHelper
{
        public static List<Type> GetSubclassesOf(Type type, bool ignoreSystem)
        {
            List<Type> lReturn = new List<Type>();
            foreach (var a in System.Threading.Thread.GetDomain().GetAssemblies())
            {
                if (ignoreSystem && a.FullName.StartsWith("System."))
                {
                    continue;
                }
                foreach (var t in a.GetTypes())
                {
                    if (t.IsSubclassOf(type) || (type.IsInterface && t.GetInterfaces().FirstOrDefault(e => e.FullName == type.FullName) != null))
                    {
                        lReturn.Add(t);
                    }
                }
            }
            return lReturn;
        }
}

这是用例的Manager类:

public class PageManager
{
    private readonly ContentPageRepository _pageRepository;
    public PageManager()
    {
        _pageRepository = RepositoryFactory.CreateDynamic<ContentPage>();
    }

    public void GetPagesByContentType(ContentType type)
    {
        var pages = _pageRepository.GetByPredicate(x => x.Status != EntityStatus.Deleted && x.Node.Type == type);
        foreach (var page in pages)
        {
            //Deal with it :)
        }

    }
}
相关问题