【问题标题】:Create new class instance / reset class instance of a class instance that is inherited from an abstact base class创建从抽象基类继承的类实例的新类实例/重置类实例
【发布时间】:2016-02-22 10:45:03
【问题描述】:

之前我想为长标题道歉,但我没有找到更短的版本。

我有一个抽象基类,它提供通用方法来访问测试类中的函数,这些函数派生自我的基类。

我有一个类集合,这些类本身具有对这些测试类的引用。

结构是:

// A really simplified example for my manager
Collection<AbstractBaseClass> Manager = new Collection<AbstractBaseClass> 
{
    TestClassA();
    TestClassB();
}

现在我需要在不知道该集合中的哪个测试类的情况下杀死并重新创建测试类集合中的实例。

我尝试做某事。喜欢(伪代码)

Manager[0] = null;
Manager[0] = new (object)Manager[0].GetType();

我已经偶然发现了 Get a new object instance from a Type,但这 - 然而 - 不起作用,因为 CreateInstance 不是 System.Activator 的成员。我也找不到 ObjectType 类。

长解释,短问题:如何从我只有一个实例的类创建一个新实例?

非常感谢,ADP。

【问题讨论】:

  • 如果 T 类型的实例仅在运行时已知,则无法构造它。
  • Activator 方法CreateInstance。请参阅MSDN。在您的代码中搜索拼写错误/缺少的引用。
  • 您需要使用Activator.CreateInstance。您应该能够弄清楚您拥有的对象的实际类型。但老实说,看起来你正在过度设计某些东西,应该有更简单的做事方式。如果您描述您想要实现的目标,可能会有更简单的解决方案。
  • 太奇怪了!我关闭了IDE,再次打开它,错误消失了。我已经尝试了 3 次,但它没有改变任何东西.... VS2015 充满了错误,太可怕了! ...
  • @oleksii:我想你是对的。我的问题是,我的程序从未打算重复任何内容。但是我的老板进来说“我们得到了这个可重复的”......

标签: c# reflection


【解决方案1】:

如果你知道你所有的类都有一个公共的无参数构造函数,你可以这样做:

manager[i] = (AbstractBaseClass)Activator.CreateInstance(manager[i].GetType());

【讨论】:

  • 谢谢李,这就是解决方案。我之前尝试过 3 次,但是一个 VS2015 IDE 错误把它搞砸了......
  • @AllDayPiano 我会看看我的答案。看起来更费力,但不应该超过 10 分钟,你会避免反思。
【解决方案2】:

虽然您可以使用 Activator.CreateInstance 从给定类型创建实例,但也许您可以使用 generics 以更优化的方式解决这个问题:

public sealed class TestCollection<T> : ICollection<T>
   where T : AbstractBaseClass, new()
{
    private List<T> Tests { get; } = new List<T>();

    public T this[int index] => Tests[index];

    public void Add(T test) => Tests.Add(test);

    // Rest of ICollection<T> members

    public void NewAt(int testIndex) => Tests[testIndex].Insert(testIndex, new T());
} 

现在您不再需要 反射因为T 必须是一个具有公共、无参数构造函数的类

TestCollection<AbstractBaseClass> manager = new TestCollection<AbstractBaseClass>();
manager.Add(new Test());
manager.Add(new Test());
manager.Add(new Test());

manager.NewAt(1);

现在您已经创建了一个新的 Test 实例,而无需对索引 1 进行反射,您仍然可以使用 TestCollectin&lt;T&gt; 索引器访问类型为 Test 的新对象:manager[1]

【讨论】:

  • 嗨,马蒂亚斯。这也是我已经在某处找到的解决方案。不幸的是,我的项目已经取得了巨大的进展,以这种方式改变它需要付出巨大的努力。我把我的问题简单化了。实际上,这种形式的我的问题中没有像postet这样的集合。该集合是另一个类,其中包含一些其他类,然后是我的参考:)
  • @AllDayPiano 好吧,那么您的问题需要更加具体...:\顺便说一句,我会将这个答案留给未来的读者
  • 嗨,Matias,如果您理解我的回答,就好像我不需要它一样,我很抱歉。当然,这一次可能不会,但总的来说这是一个不错的主意,我会将其添加为书签,以防将来需要类似的东西。但是我的经验是,最好将问题减少到 3 LOC,而冗长的解释总是会导致很长的讨论。所以我希望你能理解我:)
  • @AllDayPiano 没问题!! ;) SO 不仅要回答 OP,还要为未来的访问者提供高质量的答案。我没问题
猜你喜欢
  • 2018-07-01
  • 1970-01-01
  • 2011-12-08
  • 1970-01-01
  • 1970-01-01
  • 2019-01-06
  • 1970-01-01
  • 1970-01-01
  • 2022-10-21
相关资源
最近更新 更多