我正在挖掘几个月前我下载的MVC示例并遇到使用foreach
的{{1}}循环。我希望有人可以解释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
函数,但实际上并不了解它是如何工作的。
答案 0 :(得分:2)
值得reading a bit about AppDomains 让我们假设您了解AppDomain是什么以及它与ASP.NET的相关性 有关AppDomain.GetAssemblies方法的说明,请参阅this link。
查询正在搜索加载到当前AppDomain的程序集,以查找程序集名称中包含“Spring”的任何位置。
Spring:应用程序框架。
我认为样本中有一些功能取决于是否引用了Spring。再告诉你,我需要看看剩下的代码。
好的,这是需要解释的更多代码
因此,对于每个Spring组件(或至少在名称中具有“Spring”的组件......),我们使用反射来查看类型。
我们想要的是:
- 某些事物的子类型(t.BaseType != null
)
- 不是价值类型(t.IsClass
)
- 具体(没有抽象,没有接口 - !t.IsAbstract
),有类型参数(t.BaseType.IsGenericType
)
- 现在它变得有趣:我们正在寻找EntityTypeConfiguration<>
的子类
- 我们的某些成员可以从通用类型ta => _modelInterfaceType.IsAssignableFrom(ta))
代码找到合适的类型后,会继续为每个创建的实例在ModelBuilder
上创建每个invoke a generic method(see also)的实例。
答案 1 :(得分:0)
应用程序域(AppDomain
)只是.NET应用程序运行的沙箱环境。每个应用程序域都与其他域隔离,在大多数情况下,但并非总是如此,单个进程=单个域。
AppDomain.CurrentDomain
指的是包含当前正在执行的代码(并引用AppDomain.CurrentDomain
)的应用程序域。 GetAssemblies()
获取已加载到该域的所有程序集 - 即从System.Web.Mvc.dll上的mscorlib.dll到您引用的任何其他程序集的所有程序集。
因此,循环遍历加载到应用程序中的所有程序集(+应用程序自己的程序集),但过滤到名称包含"Spring"
的程序集。
LINQy foreach
基本上等同于:
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
if (!assembly.GetName().Name.Contains("Spring"))
{
continue;
}
// Do something
}
这种代码可用于例如通过反射在装配中找到特定类型 - 例如插件,控制器(MVC本身使用类似的代码来查找你的Controller
类)等。
在这种情况下,它正在寻找EntityTypeConfiguration<T>
的具体实现(例如EntityTypeConfiguration<SomeEntity>
),其中T
是从Type
中存储的_modelEntityInterface
派生的类型}。
然后,仍然通过Reflection,相当于这个调用:
someclass.Add<SomeEntity>(
modelBuilder.Configurations,
new object[] { new EntityTypeConfiguration<SomeEntity>() }
);
(不确定它是Add
,但是addMethod
是指在代码的前面部分中反射找到的MethodInfo
,您没有包含它 - 并且从名称该变量,方法的名称似乎可能是Add
)。