Skip to content

Commit

Permalink
Move GetAllInterfaces to ReflectionUtils
Browse files Browse the repository at this point in the history
  • Loading branch information
satano committed Jan 18, 2020
1 parent f58c714 commit b9c14a5
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 32 deletions.
4 changes: 0 additions & 4 deletions src/Mapster.Tests/DynamicTypeGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ namespace Mapster.Tests
[TestClass]
public class DynamicTypeGeneratorTests
{

private interface INotVisibleInterface
{
int Id { get; set; }
Expand Down Expand Up @@ -58,7 +57,6 @@ public void CreateTypeForSimpleInterface()
ISimpleInterface instance = (ISimpleInterface)Activator.CreateInstance(iClass);

instance.ShouldNotBeNull();
instance.ShouldBeAssignableTo<ISimpleInterface>();

instance.Id = 42;
instance.Name = "Lorem ipsum";
Expand All @@ -75,7 +73,6 @@ public void CreateTypeForInheritedInterface()
IInheritedInterface instance = (IInheritedInterface)Activator.CreateInstance(iClass);

instance.ShouldNotBeNull();
instance.ShouldBeAssignableTo<IInheritedInterface>();

instance.Id = 42;
instance.Name = "Lorem ipsum";
Expand All @@ -94,7 +91,6 @@ public void CreateTypeForComplexInterface()
IComplexInterface instance = (IComplexInterface)Activator.CreateInstance(iClass);

instance.ShouldNotBeNull();
instance.ShouldBeAssignableTo<IComplexInterface>();

instance.Id = 42;
instance.Name = "Lorem ipsum";
Expand Down
27 changes: 1 addition & 26 deletions src/Mapster/Utils/DynamicTypeGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
Expand Down Expand Up @@ -47,7 +46,7 @@ private static Type CreateTypeForInterface(Type interfaceType)
{
TypeBuilder builder = _moduleBuilder.DefineType("GeneratedType_" + Interlocked.Increment(ref _generatedCounter));

foreach (Type currentInterface in GetAllInterfaces(interfaceType))
foreach (Type currentInterface in ReflectionUtils.GetAllInterfaces(interfaceType))
{
builder.AddInterfaceImplementation(currentInterface);
foreach (PropertyInfo prop in currentInterface.GetProperties())
Expand All @@ -71,30 +70,6 @@ private static Type CreateTypeForInterface(Type interfaceType)
#endif
}

// GetProperties() and GetMethods() do not return properties/methods from parent interfaces,
// so we need to process every one of them.
private static IEnumerable<Type> GetAllInterfaces(Type interfaceType)
{
var allInterfaces = new List<Type>();
var interfaceQueue = new Queue<Type>();
allInterfaces.Add(interfaceType);
interfaceQueue.Enqueue(interfaceType);
while (interfaceQueue.Count > 0)
{
var currentInterface = interfaceQueue.Dequeue();
foreach (var subInterface in currentInterface.GetInterfaces())
{
if (allInterfaces.Contains(subInterface))
{
continue;
}
allInterfaces.Add(subInterface);
interfaceQueue.Enqueue(subInterface);
}
}
return allInterfaces;
}

private static void CreateProperty(Type interfaceType, TypeBuilder builder, PropertyInfo prop)
{
const BindingFlags interfacePropMethodFlags = BindingFlags.Instance | BindingFlags.Public;
Expand Down
43 changes: 41 additions & 2 deletions src/Mapster/Utils/ReflectionUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,57 @@ public static IEnumerable<IMemberModelEx> GetFieldsAndProperties(this Type type,
{
var bindingFlags = BindingFlags.Instance | accessorFlags;

var properties = type.GetProperties(bindingFlags)
IEnumerable<IMemberModelEx> getPropertiesFunc(Type t) => t.GetProperties(bindingFlags)
.Where(x => x.GetIndexParameters().Length == 0)
.Where(x => !requireSetter || x.CanWrite)
.Select(CreateModel);

var fields = type.GetFields(bindingFlags)
IEnumerable<IMemberModelEx> getFieldsFunc(Type t) => t.GetFields(bindingFlags)
.Where(x => !requireSetter || !x.IsInitOnly)
.Select(CreateModel);

IEnumerable<IMemberModelEx> properties;
IEnumerable<IMemberModelEx> fields;

if (type.IsInterface)
{
IEnumerable<Type> allInterfaces = GetAllInterfaces(type);
properties = allInterfaces.SelectMany(currentInterface => getPropertiesFunc(currentInterface));
fields = allInterfaces.SelectMany(currentInterface => getFieldsFunc(currentInterface));
}
else
{
properties = getPropertiesFunc(type);
fields = getFieldsFunc(type);
}

return properties.Concat(fields);
}

// GetProperties(), GetFields(), GetMethods() do not return properties/methods from parent interfaces,
// so we need to process every one of them separately.
public static IEnumerable<Type> GetAllInterfaces(Type interfaceType)
{
var allInterfaces = new List<Type>();
var interfaceQueue = new Queue<Type>();
allInterfaces.Add(interfaceType);
interfaceQueue.Enqueue(interfaceType);
while (interfaceQueue.Count > 0)
{
var currentInterface = interfaceQueue.Dequeue();
foreach (var subInterface in currentInterface.GetInterfaces())
{
if (allInterfaces.Contains(subInterface))
{
continue;
}
allInterfaces.Add(subInterface);
interfaceQueue.Enqueue(subInterface);
}
}
return allInterfaces;
}

public static bool IsCollection(this Type type)
{
return typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()) && type != typeof(string);
Expand Down

0 comments on commit b9c14a5

Please sign in to comment.