【问题标题】:Activator.CreateInstance with dynamic TypeActivator.CreateInstance 与动态类型
【发布时间】:2018-03-05 20:27:25
【问题描述】:

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

我的做法:

        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。

提前感谢您的澄清。

马蒂亚斯

【问题讨论】:

    标签: c#


    【解决方案1】:

    有一个使用区别...当你写:

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

    您将 Class 用作 Type,这是一种很好的方法。 您使用了引用类类型的泛型类型。

    但是有:

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

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

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

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

    我希望清楚。

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

    【讨论】:

    • 对不起,我可能只是愚蠢。根据关于typeof的MSDN:“用于获取类型的System.Type对象。typeof表达式采用以下形式:”类型通常也只是一个类,如果我进入它:公共抽象类类型:MemberInfo,_Type , IReflect 那么我不是一直都有一个Instance,否则Reference就是Nul​​l了?
    • 不,你不是。 ;) Type 是一个类(模式),但就像你说的,typeof 创建一个类 Type(模式)的对象(实例)。为了你的理解,你可以用 Activator.CreateInstance() 替换 typeof。这有点复杂,因为在这种情况下,您的 Type 对象将是您的类(模式)的描述。
    • 我想我明白了:类型可以是类型类型(wtf?)或方案的实例。你知道这个方案是如何标记或保存的吗?但到目前为止我的问题已经得到解答。
    • 有一些语法规范...单词的第一个字母是引用一个类(模式)。当说模式时,它是为了描述一个类的“效用”,如果你愿意,它就像一个蓝图。但是,是的,您可以拥有一个 Type 类的对象(实例)来描述类 Type。
    【解决方案2】:

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

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

    这就是为什么有一个Activator.CreateInstance(typeGoesHere) 函数的非通用形式,它可以用于我们在创建时没有强类型的情况目的。所以我们可以将类型作为参数传递给该函数。我们可以通过多种方式提供类型变量。在您的情况下,您会在程序集中找到正确的类型,如下所示:

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

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

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

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

    【讨论】:

    • 抱歉,我将“强类型”用于其他用途:您的意思是“强类型”是一种在编译时已知的类型?并且没有办法使显式转换成为可能?并且:是否有指标,何时需要强类型,何时不需要?通常它们都是 System.Type?
    • 强类型是“类型名称”而不是该类型的变量。例如 string 是 Strong Type 但是当我们编码 string name = "Matthias" name.GetType() 是一个变量形式的字符串类型。是的,编译器在编译时就知道强类型。正如我所说,进行显式转换的唯一方法是提供强类型名称而不是该类型的变量。
    • 所有泛型版本的方法和类型如 List 必须由强类型提供。如果您没有强类型,则必须提供类型作为该类型的实例 [typeof()] 可以在这种情况下使用。或者你可以在像你这样的场景中使用反射。
    • 你有例子吗?据我所知,typeof 仅适用于 Compile-Types:typeof 采用类型名称(您在编译时指定)。
    • 我的意思是 typeof(Strong Type) 会给出一个强类型的实例,以便在您需要类型实例而不是强类型的情况下使用它。那么你得到你的答案了吗?如果我的回答有用,请标记它。
    【解决方案3】:

    这里是纯动态方式。

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

        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;
        }
    }
    

    这是 Entity 和 Repository 之间映射类型的帮助类。

    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 :)
            }
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-28
      • 1970-01-01
      • 2011-03-27
      • 2014-07-24
      • 2012-08-07
      • 2012-11-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多