简体   繁体   English

如何将对象转换为Type属性中定义的类型?

[英]How can I cast an object as a type defined in a Type property?

I have class that looks something like this: 我的课程看起来像这样:

public RepositoryManager
{
    public Type Context {get; private set;}

    public RepositoryManager(Type context)
    {
        Context = context;
    }

    public IRepository<T> GetRepository<T>() where T : class
    {
        // create an instance of Context to pass to repo ctor
        var contextInstance = Activator.CreateInstance(Context);  // fail
        return new Repository<T>(contextInstance);
    }
}

I know I need to cast contextInstance as the type of Context but I'm not sure how to do this. 我知道我需要将contextInstance作为Context的类型,但我不知道如何做到这一点。 I can't do typeof(Context) because the compiler complains I am using a property like a 'type' (which is my intent in this case). 我不能做typeof(Context)因为编译器抱怨我使用了像'type'这样的属性(在这种情况下我的意图)。

How can I pass an instance of the type stored in the Context property to the constructor of the Repository object? 如何将Context属性中存储的类型实例传递给Repository对象的构造函数?

Update/Clarifications 更新/澄清

Based on some of the answers it appears I did not explain myself clearly. 基于一些答案,我似乎没有清楚地解释自己。

The type I am storing in the Context property is most likely going to be an implementation of DbContext... for example SailingDbContext created by Entity Framework code first reverse engineering. 我在Context属性中存储的类型很可能是DbContext的实现...例如由实体框架代码第一次逆向工程创建的SailingDbContext。 It can also be JudoDbContext. 它也可以是JudoDbContext。 Or some other completely unrelated context. 或者其他一些完全无关的背景。 I have no idea what it might be. 我不知道它可能是什么。 However, I do know that that type will be available to the assembly. 不过,我知道该类型将提供给大会。

The T in Repository will be come kind of POCO. 存储库中的T将会出现POCO。 Perhaps Customer, or Products. 也许客户或产品。 I don't really know and I don't care... I just know it will exist. 我真的不知道,我也不在乎......我只知道它会存在。

The constructor for Repository needs to be passed an instance of the type defined in the Context property. 需要为Repository的构造函数传递Context属性中定义的类型的实例。 This is the point of my question. 这是我的问题。 How can I cast the object created by Activator to the type defined in the Context property? 如何将Activator创建的对象强制转换为Context属性中定义的类型?

Per request, I am adding the constructor for Repository class. 根据请求,我添加了Repository类的构造函数。 However, I fear this will confuse things further. 但是,我担心这会使事情进一步混乱。 I don't see how attempting to cast an instance of object an object created by Activator to a type defined in a property can be influenced by what the instance is getting passed to. 我没有看到如何尝试将Activator创建的对象的对象实例转换为属性中定义的类型,这可能会受到实例传递给的内容的影响。

public class Repository<T> : IRepository<T>, IDisposable where T : class
{

    private readonly DbSet<T> _dbSet;
    public DbContext Context {get; set;}

    public Repository() 
    {
        // dont use ...
    }

    public Repository(DbContext context)
    {
        Context = context;
        _dbSet = Context.Set<T>();
    }

    // lots more code snipped
 }

Keep in mind that this is a concrete implementation of the IRepository interface. 请记住,这是IRepository接口的具体实现。 Casting the object created by Activator directly to a type DbContext is not a good answer. 将Activator创建的对象直接转换为类型DbContext并不是一个好的答案。

Again, I'm just trying to cast an object to a type defined in the Context property. 同样,我只是试图将对象强制转换为Context属性中定义的类型。

You need to use "dynamic" instead of "var" to get the benefits of dynamic creation at run-time. 您需要使用“dynamic”而不是“var”来获得运行时动态创建的好处。 "var" resolution/validation still occurs at compile time. “var”解析/验证仍然在编译时发生。

dynamic contextInstance = Activator.CreateInstance(Context);

You can create generic type dynamically with help of MakeGenericType and then cast it simply: 您可以在MakeGenericType的帮助下动态创建泛型类型,然后简单地转换它:

public class RepositoryManager
{
    public Type Context { get; private set; }

    public RepositoryManager(Type context)
    {
        Context = context;
    }

    public IRepository<T> GetRepository<T>() where T : class
    {
        var contextInstance = Activator.CreateInstance(Context);
        var repositoryType = typeof(Repository<>).MakeGenericType(Context);
        var repository = Activator.CreateInstance(repositoryType, contextInstance);
        return (IRepository<T>)repository;
    }
}

i suggest you use UnitOfWork pattern with Repository: 我建议你使用UnitOfWork模式和Repository:

public class SqlRepository<T>: IRepository<T> where T: class, IEntity
{
    protected readonly DbSet<T> _objectSet;

    public SqlRepository(ApplicationDbContext context)
    {
        _objectSet = context.Set<T>();

    }
}

and you UnitOfWork class: 而你UnitOfWork类:

public class SqlUnitOfWork<T> : IUnitOfWork<T> where T : class, IEntity
{
    private ApplicationDbContext _db;
    public SqlUnitOfWork(ApplicationDbContext context)
    {
        _db = context;
    }

    public IRepository<T> Repistory
    {
        get
        {
            return new SqlRepository<T>(_db);
        }
    }

} }

in asp.net mvc some times you need other type repository on same controller for examle lets say you need to query accounts in PersonController then in this pattern you easily can write something like this in you unitOfWork: 在asp.net mvc中有时候你需要在同一个控制器上使用其他类型的存储库来进行测试让我们说你需要在PersonController中查询帐户然后在这个模式中你可以轻松地在你的unitOfWork中写这样的东西:

    public IRepository<TEntity> GetTypeRepository<TEntity>() where TEntity : class, IEntity
    {
        return new SqlRepository<TEntity>(_db);
    }

this way you dont need to instatiate a new context every time you need new repository. 这样,每次需要新的存储库时,您都不需要实例化新的上下文。 i skiped interface definitions btw. 我顺利接口定义了。 hope it helps. 希望能帮助到你。 :) :)

你试试这个吗?

var contextInstance = Activator.CreateInstance("YourAssemblyFullName", Context.FullName);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM