using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using FreeSql;
using FreeSql.DataAnnotations;
using FreeSql.Extensions.EfCoreFluentApi;
using FreeSql.Internal.CommonProvider;
partial class FreeSqlDbContextExtensions
{
///
/// EFCore 95% 相似的 FluentApi 扩展方法
///
///
///
///
///
public static ICodeFirst Entity(this ICodeFirst codeFirst, Action> modelBuilder)
{
var cf = codeFirst as CodeFirstProvider;
codeFirst.ConfigEntity(tf => modelBuilder(new EfCoreTableFluent(cf._orm, tf)));
return codeFirst;
}
///
/// EFCore 95% 相似的 FluentApi 扩展方法
///
///
/// 实体类型
///
///
public static ICodeFirst Entity(this ICodeFirst codeFirst, Type entityType, Action modelBuilder)
{
var cf = codeFirst as CodeFirstProvider;
codeFirst.ConfigEntity(entityType, tf => modelBuilder(new EfCoreTableFluent(cf._orm, tf, entityType)));
return codeFirst;
}
public static ICodeFirst ApplyConfiguration(this ICodeFirst codeFirst, IEntityTypeConfiguration configuration) where TEntity : class
{
return codeFirst.Entity(eb =>
{
configuration.Configure(eb);
});
}
#if net40
#else
static IEnumerable GetExtensionMethods(this Assembly assembly, Type extendedType)
{
var query = from type in assembly.GetTypes()
where !type.IsGenericType && !type.IsNested
from method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
where method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false)
where method.GetParameters()[0].ParameterType == extendedType
select method;
return query;
}
///
/// 根据Assembly扫描所有继承IEntityTypeConfiguration<T>的配置类
///
///
///
///
///
public static ICodeFirst ApplyConfigurationsFromAssembly(this ICodeFirst codeFirst, Assembly assembly, Func predicate = null)
{
IEnumerable typeInfos = assembly.DefinedTypes.Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition);
MethodInfo methodInfo = typeof(FreeSqlDbContextExtensions).Assembly.GetExtensionMethods(typeof(ICodeFirst))
.Single((e) => e.Name == "Entity" && e.ContainsGenericParameters);
if (methodInfo == null) return codeFirst;
foreach (TypeInfo constructibleType in typeInfos)
{
if (constructibleType.GetConstructor(Type.EmptyTypes) == null || predicate != null && !predicate(constructibleType))
{
continue;
}
foreach (var @interface in constructibleType.GetInterfaces())
{
if (@interface.IsGenericType && @interface.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>))
{
var type = @interface.GetGenericArguments().First();
var efFluentType = typeof(EfCoreTableFluent<>).MakeGenericType(type);
var actionType = typeof(Action<>).MakeGenericType(efFluentType);
//1.需要实体和Configuration配置
//codeFirst.Entity(eb =>
//{
// new ToDoItemConfiguration().Configure(eb);
//});
//2.需要实体
//Action> x = new Action>(e =>
//{
// object o = Activator.CreateInstance(constructibleType);
// constructibleType.GetMethod("ApplyConfiguration")?.Invoke(o, new object[1] { e });
//});
//codeFirst.Entity(x);
//3.实现动态调用泛型委托
DelegateBuilder delegateBuilder = new DelegateBuilder(constructibleType);
MethodInfo applyconfigureMethod = delegateBuilder.GetType().GetMethod("ApplyConfiguration")?.MakeGenericMethod(type);
if (applyconfigureMethod == null) continue;
Delegate @delegate = Delegate.CreateDelegate(actionType, delegateBuilder, applyconfigureMethod);
methodInfo.MakeGenericMethod(type).Invoke(null, new object[2]
{
codeFirst,
@delegate
});
}
}
}
return codeFirst;
}
class DelegateBuilder
{
private readonly Type type;
public DelegateBuilder(Type type)
{
this.type = type;
}
public void ApplyConfiguration(EfCoreTableFluent ex)
{
object o = Activator.CreateInstance(type);
type.GetMethod("Configure")?.Invoke(o, new object[1] { ex });
}
}
#endif
}