Skip to content

Instantly share code, notes, and snippets.

@hidegh
Created March 7, 2017 08:57
Show Gist options
  • Select an option

  • Save hidegh/36d92380c720804dee043fde8a863ecb to your computer and use it in GitHub Desktop.

Select an option

Save hidegh/36d92380c720804dee043fde8a863ecb to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Reflection;
namespace EF6x_code_first_persistence.Mappings.Core
{
/// <summary>
/// Allows us to register conventions with a single call and also to pass in custom NamespaceToDbSchemaConvertor in ctor if given custom IConvention supports it.
/// </summary>
public static class MappingExtensions
{
public delegate bool MappingFilterDelegate(Type mappingClass, Type entity);
public static void RegisterMappingsFrom<TAssembly>(this DbModelBuilder modelBuilder, MappingFilterDelegate filter = null)
{
var mappingsAssembly = typeof(TAssembly);
var entityTypeConfigurationTypesToRegister = mappingsAssembly.Assembly
.GetTypes()
.Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>))
.Where(type =>
{
var entity = type.BaseType.GetGenericArguments()[0];
var mappingClass = type;
if (filter == null)
return true;
return filter(mappingClass, entity);
})
.ToList();
foreach (var entityTypeconfigurationType in entityTypeConfigurationTypesToRegister)
{
dynamic configurationInstance = Activator.CreateInstance(entityTypeconfigurationType);
modelBuilder.Configurations.Add(configurationInstance);
}
}
public static void RegisterMappingsFromInsideAssemblyAndNamespaceOf<TMapMarker>(this DbModelBuilder modelBuilder, MappingFilterDelegate filter = null)
{
var mappingMarker = typeof(TMapMarker);
var mappingMarkerNS = mappingMarker.Namespace;
RegisterMappingsFrom<TMapMarker>(modelBuilder, (mappingClass, entity) =>
{
// make sure we're inside the desired namespace
if (!mappingClass.FullName.StartsWith(mappingMarkerNS + "."))
return false;
// do additional custom filter logic
if (filter == null)
return true;
return filter(mappingClass, entity);
});
}
public static void IgnoreNonMappedProperties<T>(this EntityTypeConfiguration<T> mapper) where T : class
{
var entityType = typeof(T);
var entityProperties = entityType
.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(c => c.GetMethod != null && c.GetMethod.IsPrivate == false)
.ToArray();
var mapperType = mapper.GetType();
var configuration = mapperType
.GetProperty("Configuration", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(mapper);
var configurationType = configuration.GetType();
var configuredProperties = ((IEnumerable<PropertyInfo>)
configurationType
.GetProperty("ConfiguredProperties", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(configuration)
)
.ToArray();
var configurationIgnoreMethod = configurationType.GetMethod("Ignore");
foreach (var p in entityProperties)
{
// skip if property is mapped...
if (configuredProperties.FirstOrDefault(c => c.Name == p.Name) != null)
continue;
// ignore properties that aren't mapped manually...
configurationIgnoreMethod.Invoke(configuration, new object[] { p });
}
}
}
}
/*
* https://github.com/aspnet/EntityFramework/issues/2805
*
* https://daveaglick.com/posts/custom-entity-type-configurations-in-entity-framework-code-first-part-1
* https://daveaglick.com/posts/custom-entity-type-configurations-in-entity-framework-code-first-part-2
*/
@hidegh

hidegh commented Apr 4, 2017

Copy link
Copy Markdown
Author

FAIL:
This seems to work fine, but messes up bidirectional 1:N relations, where parent does it's configuration for both of the side, so configuring (N:1) from the child side won't be possible (EF won't allow it) and thus the back-ref. property will be ignored, even in case where we wan't to use it...

As a desperate measure to avoid un-mapping of custom properties on my entities I decided to use get/set functions...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment