【问题标题】:C# Activator.CreateInstance generic instance getting lostC# Activator.CreateInstance 通用实例丢失
【发布时间】:2014-11-03 03:37:46
【问题描述】:

仅供参考:冗长的序言是为了帮助解释我为什么使用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();
}

为“处理程序”类定义一个接口,即这些类实现上面列出的查询操作。

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

正如您在Databases 构造函数中看到的那样,现在编写代码的方式,我得到一个NullReferenceException,即使EntityNReader 的实例r 已创建并且(已验证为)不为空。

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

这里发生了什么? Link to actual code if necessary. 附言我对编程比较陌生,所以我很乐意听取经验开发人员如何设计这个组件(特别是如果我走错了路)。

【问题讨论】:

    标签: c# orm factory late-binding activator


    【解决方案1】:

    我意识到您的代码只是示例,但我马上就发现了这一点...

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

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

    【讨论】:

    • 不抱歉。我注意到了,修复了它,只是还没有将更改推送到 github(对不起)。上面的问题是在我做出改变之后出现的。我只是推送了更改。
    猜你喜欢
    • 2020-02-05
    • 2021-11-13
    • 1970-01-01
    • 2013-10-27
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多