1

I was digging though an MVC example that I downloaded a few months ago and ran across a foreach loop that uses the AppDomain.CurrentDomain. I was hoping someone could explain what the foreach loop is searching for.

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

I do understand that runs the loop one time per assembly that it finds in the AppDomain.CurrentDomain.GetAssemblies and the .Where() is just a filter but I am not really sure how that filter is working or the data it is searching for in the AppDomain.

Note: I have never used the AppDomain function and really don't understand how it works.

2 Answers2

2

It may be worth reading a bit about AppDomains.
Let's assume you understand what an AppDomain is and how it is relevant to ASP.NET.
See this link for an explanation of the AppDomain.GetAssemblies method.

The query is searching the assemblies loaded into the current AppDomain to find any where the name of the assembly contains "Spring".

Spring: an application framework.

I would assume that there is some functionality in the sample that is dependent on whether or not Spring is referenced. To tell you any more I would need to see the rest of the code.

After Edit by @Matthew Verstraete#

OK, that is a little bit more code to explain.
So, for each Spring assembly (or at least assembly that has "Spring" in the name...) we are using reflection to look at the types.
We want things that are:
- subtypes of something (t.BaseType != null)
- aren't value types (t.IsClass)
- are concrete (no abstract, no interfaces - !t.IsAbstract), have type parameters (t.BaseType.IsGenericType)
- now it gets interesting: we are looking for subclasses of EntityTypeConfiguration<>
- where some member of our can be assigned from the generic type ta => _modelInterfaceType.IsAssignableFrom(ta))

Once the code has found suitable types it continues on to create an instance of each invoke a generic method (see also) on ModelBuilder for each created instance.

What you are digging through is code first configuration of entity framework.

Community
  • 1
  • 1
Hamish Smith
  • 8,153
  • 1
  • 34
  • 48
  • Thanks for this explanation and the link to the dynamic model. The example I downloaded does include a DynamicDbContext and the link to the code first configuration talks about the method the example is using. –  Aug 10 '13 at 21:28
  • No worries @MatthewVerstraete. That's what this site is for isn't it? – Hamish Smith Aug 10 '13 at 21:41
0

An application domain (AppDomain) is simply a sandbox environment that a .NET application runs in. Each application domain is isolated from the others, and in most cases, but not always, a single process = a single domain.

AppDomain.CurrentDomain refers to the application domain that contains the code that is currently executing (and referencing AppDomain.CurrentDomain). GetAssemblies() gets all assemblies that have been loaded into that domain - i.e. everything from mscorlib.dll over System.Web.Mvc.dll to any other assemblies you've referenced.

So, the loop goes through all the assemblies loaded into your application (+ your application's own assembly), but filtered to assemblies whose name contains "Spring".

The LINQy foreach is essentially equivalent to:

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

This kind of code may be used to e.g. find specific types in the assembly by Reflection - e.g. plugins, controllers (MVC itself uses similar code to find your Controller classes) etc.

In this case, it's looking for concrete implementations of EntityTypeConfiguration<T> (for example EntityTypeConfiguration<SomeEntity>) where T is a type derived from the Type stored in _modelEntityInterface.

It then, still through Reflection, does the equivalent of this call:

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

(not certain it's Add, but addMethod refers to a MethodInfo found by Reflection in an earlier part of the code, which you haven't included - and from the name of that variable, it seems likely the method's name is Add).

JimmiTh
  • 7,389
  • 3
  • 34
  • 50