C#激活器.CreateInstance通用实例丢失

本文关键字:实例 激活 CreateInstance | 更新日期: 2023-09-27 18:28:54

FYI:详细的序言有助于解释我使用Activator.CreateInstance的原因。我有许多实体(与数据库列信息相对应的对象)"包含"在多个数据库中,每个数据库都有不同的表/列设置。因此,我可以从每个数据库中检索一个实体,但每个数据库检索实体的方式不同。数据库类型直到运行时才知道,并且在整个执行过程中可能会有所不同。我已经创建了以下设置:

首先定义每个实体应该支持的查询操作,每个实体读取器应该支持这些操作。

public abstract class Operations<T> {
    public delegate T findDelegate(int id);
    public findDelegate find;
}
// there are many of these N=1,2,..., but here is one
// use abstract class since implementation of queries should be done by handlers
public class EntityNReader : Operations<EntityN> {
    public Reader();
}

为"Handler"类定义一个接口,即这些类实现上面列出的查询操作。

public interface IHandler<T> {
    public string find(int id);
}
// there are many of these N,M=1,2..., but here is one
// use of interface is to force handlers to implement all query types
public class EntityNHandlerForDbTypeM : IHandler<EntityN> {
    public string find(int id) {/*whatever*/}
}

这允许开发人员创建一个单独的类来处理DbTypeMEntityN查询操作。现在,创建一个包含读取器对象并将处理程序方法绑定到读取器委托的Database类。

public class Database {
    // there are many of these, but here is one
    public EntityNReader EntitiesN;
    public Database(string dbType) {
        // this is called for each EntityNReader
        bindHandlers<Reader, TypeN>(MyReader, dbType);
        // ...
        // nullreferenceexception
        EntitiesN.find(0);
    }
    // this is a factory that also performs late binding
    private void bindHandlers<T,K>(T reader, string dbTypeM)
        where T: Operations<K>, new()
    {
        // create instance of EntityNReader
        r = (T)Activator.CreateInstance(typeof(T));
        // r != null
        // create instance of handler
        IHandler<K> h = (IHandler<K>)(Activator.CreateInstance(
            Type.GetType("namespace.to.EntityNHandlerForDbTypeM"),
            new object[] { this }
        ));
        // bind delegates
        r.find = h.find;
    }
}

正如您在Database的构造函数中看到的那样,按照现在编写代码的方式,即使创建了EntityNReader的实例r并且(验证为)不是null,我也会得到NullReferenceException

但是,如果我实例化EntitiesN,它在Database中声明,而不是在bindHandlers中声明,那么代码就会编译,一切都正常。我不这么做的原因是(随后)我想在Database类实例化时,在bindHandlers内部有条件地创建读取器/处理程序。

这里发生了什么?如有必要,链接到实际代码。附言:我对编程还比较陌生,所以我很乐意听取经验丰富的开发人员如何设计这个组件(尤其是如果我走错了路)。

C#激活器.CreateInstance通用实例丢失

我知道你的代码只是样本,但我一开始就发现了。。。

if (supports[typeof(Entity1).Name]) { bindHandlers<Entity1Reader, Entity1>(Entities1, CamaDbType); }
if (supports[typeof(Entity2).Name]) { bindHandlers<Entity1Reader, Entity1>(Entities1, CamaDbType); }

你可能有一个简单的复制/粘贴错误吗?请注意,两个bindHandlers调用都传入了Entities1。