1

我正在挖掘几个月前下载的一个 MVC 示例,并遇到了一个foreach使用AppDomain.CurrentDomain. 我希望有人可以解释foreach循环正在搜索什么。

foreach (var assembly in AppDomain.CurrentDomain
              .GetAssemblies()
              .Where(a => a.GetName().Name.Contains("Spring")))
        {
            var configTypes = assembly
              .GetTypes()
              .Where(t => t.BaseType != null
                && t.IsClass
                && !t.IsAbstract
                && t.BaseType.IsGenericType
                && t.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>)
                && t.BaseType.GetGenericArguments().Any(ta => _modelInterfaceType.IsAssignableFrom(ta)));

            foreach (var type in configTypes)
            {
                var entityType = type.BaseType.GetGenericArguments().Single();

                var entityConfig = assembly.CreateInstance(type.FullName);

                addMethod.MakeGenericMethod(entityType)
                  .Invoke(modelBuilder.Configurations, new object[] { entityConfig });
            }
        }

我确实理解它在 中找到的每个程序集运行一次循环,AppDomain.CurrentDomain.GetAssemblies并且.Where()只是一个过滤器,但我不确定该过滤器是如何工作的或它在AppDomain.

注意:我从未使用过该AppDomain功能,并且真的不明白它是如何工作的。

4

2 回答 2

2

可能值得阅读一些关于 AppDomains 的内容
让我们假设您了解 AppDomain 是什么以及它与 ASP.NET 的关系。有关AppDomain.GetAssemblies 方法的说明,
请参阅此链接。

该查询正在搜索加载到当前 AppDomain 中的程序集,以查找程序集名称包含“Spring”的任何位置。

Spring:一个应用程序框架。

我会假设示例中有一些功能取决于是否引用了 Spring。要告诉您更多信息,我需要查看其余代码。

@Matthew Verstraete 编辑后#

好的,这是要解释的更多代码。
因此,对于每个 Spring 程序集(或至少名称中包含“Spring”的程序集......),我们使用反射来查看类型。
我们想要的东西是:
- 某物的子类型 ( t.BaseType != null)
- 不是值类型 ( t.IsClass)
- 是具体的(没有抽象,没有接口 - !t.IsAbstract),有类型参数 ( t.BaseType.IsGenericType)
- 现在变得有趣了:我们正在寻找EntityTypeConfiguration<>
-我们的某些成员可以从泛型类型中分配ta => _modelInterfaceType.IsAssignableFrom(ta))

一旦代码找到合适的类型,它就会继续创建一个实例,每个实例都会为每个创建的实例调用一个泛型方法另请参阅ModelBuilder

您正在挖掘的是实体框架的代码优先配置

于 2013-08-10T20:40:43.813 回答
0

应用程序域AppDomain

AppDomain.CurrentDomain包含当前正在执行(和引用AppDomain.CurrentDomain)的代码的应用程序域。GetAssemblies()获取已加载到该域中的所有程序集 - 即从 mscorlib.dll 通过 System.Web.Mvc.dll 到您引用的任何其他程序集的所有内容。

因此,循环遍历加载到您的应用程序中的所有程序集(+ 您的应用程序自己的程序集),但过滤到名称包含"Spring".

LINQyforeach本质上等同于:

foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
   if (!assembly.GetName().Name.Contains("Spring"))
   {
      continue;
   }
   // Do something
}

这种代码可用于例如通过反射查找程序集中的特定类型 - 例如插件、控制器(MVC 本身使用类似的代码来查找您的Controller类)等。

在这种情况下,它正在寻找EntityTypeConfiguration<T>(例如EntityTypeConfiguration<SomeEntity>) where的具体实现,其中T是从Type存储的_modelEntityInterface.

然后,它仍然通过反射,执行与此调用等效的操作:

someclass.Add<SomeEntity>(
   modelBuilder.Configurations, 
   new object[] { new EntityTypeConfiguration<SomeEntity>() }
);

(不确定它是Add,但addMethod指的是MethodInfoReflection 在代码的较早部分中找到的,您没有包括在内 - 从该变量的名称来看,方法的名称似乎很可能是Add)。

于 2013-08-10T20:47:55.010 回答