简体   繁体   English

在C#中使用反射和通用属性

[英]Work with reflection and generic properties in C#

I have a interface/class in my ASP.NET MVC application where all my generic repositories are referenced. 我的ASP.NET MVC应用程序中有一个接口/类,其中引用了我的所有通用存储库。 This looks something like this: 看起来像这样:

public interface IDb
{
    IGenericRepository<Car> CarRepository { get; }
    ...
    IGenericRepository<User> UserRepository { get; }
}

My goal is to find all types in an assembly which implement a certain interface and then find the corresponding generic repository to fetch some objects from the database. 我的目标是在实现某个接口的程序集中找到所有类型,然后找到相应的通用存储库以从数据库中获取某些对象。 This should work: 这应该工作:

List<IVehicle> vehicleElements = new List<IVehicle>();

Type vehicleType = typeof(IVehicle);
Type dbType = typeof(IDb);
foreach (Type type in vehicleType.Assembly.GetTypes().Where(t => t.IsClass && t.GetInterfaces().Contains(vehicleType)))
    {
        PropertyInfo repositoryInfo = dbType.GetProperties().Where(p => p.PropertyType.GenericTypeArguments.Contains(type)).SingleOrDefault();
        if (repositoryInfo != null)
        {
            var repository = repositoryInfo.GetValue(this.db);
            // TODO: work with repository
        }
    }

return vehicleElements;

My problem is that I don't know how to cast the repository variable to the needed generic IGenericRepository... Any ideas? 我的问题是我不知道如何将存储库变量转换为所需的通用IGenericRepository ...有什么想法吗?

What you want to do can't work, because in order to have a stronlgy typed repository you would need to know the type at compile time that implements your interface. 您要执行的操作无法正常工作,因为要拥有可靠的类型化存储库,您需要在编译时知道实现接口的类型。 But you only know it at runtime. 但是您只在运行时知道它。

One solution is to introduce a non-generic repository. 一种解决方案是引入非通用存储库。

Another solution is to use the dynamic keyword. 另一种解决方案是使用dynamic关键字。

dynamic repository = repositoryInfo.GetValue(this.db);
repository.SomeMethod(...);

However, this means that the compiler no longer can check the code that involves this dynamic variable. 但是,这意味着编译器不再可以检查涉及此动态变量的代码。 In other words: If SomeMethod doesn't exist on the actual type of repository a runtime exception will be thrown instead of a compiler error. 换句话说:如果repository的实际类型上不存在SomeMethod ,则将引发运行时异常,而不是编译器错误。

I'd go with a base IRepository interface with the common methods you need to interact with in this code. 我将使用基本的IRepository接口以及您需要在此代码中进行交互的常用方法。

If that's not possible for some reason you could go with a loosely coupled approach by casting to dynamic or grabbing the methods you need via reflection. 如果由于某种原因无法实现,则可以采用松散耦合的方法,将其强制转换为动态方法,或者通过反射获取所需的方法。

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

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