Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 49 additions & 1 deletion src/Mapster.Tests/WhenMappingToInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ namespace Mapster.Tests
[TestClass]
public class WhenMappingToInterface
{

#region Tests
[TestInitialize]
public void Setup()
{
Expand Down Expand Up @@ -266,6 +268,52 @@ public void MappingToInteraceWithReadonlyProps_AllPropsInitialized()
);
}

/// <summary>
/// https://github.com/MapsterMapper/Mapster/issues/723
/// </summary>
[TestMethod]
public void MappingToInteraceWithIgnorePrivateSetProperty()
{
TypeAdapterConfig<InterfaceSource723, InterfaceDestination723>
.NewConfig()
.TwoWays()
.Ignore(dest => dest.Ignore);

InterfaceSource723 dataSourse = new Data723() { Inter = "IterDataSourse", Ignore = "IgnoreDataSourse" };
InterfaceDestination723 dataDestination = new Data723() { Inter = "IterDataDestination", Ignore = "IgnoreDataDestination" };

var idestination = dataDestination.Adapt<InterfaceDestination723>();
var isourse = dataDestination.Adapt<InterfaceSource723>();

var result = dataSourse.Adapt(dataDestination);

idestination.Ignore.ShouldBeNull(); // Not create initializer and param in constructor
idestination.Inter.ShouldBe("IterDataDestination");

result.Ignore.ShouldBe("IgnoreDataDestination");
result.Inter.ShouldBe("IterDataSourse");
}

#endregion Tests

#region TestClasses
public interface InterfaceDestination723 : InterfaceSource723
{
public string Ignore { get; }
}

public interface InterfaceSource723
{
public string Inter { get; set; }
}

private class Data723 : InterfaceDestination723
{
public string Ignore { get; set; }

public string Inter { get; set; }
}

public interface IInheritedDtoWithoutProperties : IInheritedDto
{
}
Expand Down Expand Up @@ -374,6 +422,6 @@ public class PropertyInitializationTestSource
public int Property1 { get; set; }
public int Property2 { get; set; }
}

#endregion TestClasses
}
}
2 changes: 1 addition & 1 deletion src/Mapster/Adapters/ReadOnlyInterfaceAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ protected override Expression CreateInstantiationExpression(Expression source, E
if (arg.GetConstructUsing() != null)
return base.CreateInstantiationExpression(source, destination, arg);

var destType = DynamicTypeGenerator.GetTypeForInterface(arg.DestinationType, arg.Settings.Includes.Count > 0);
var destType = DynamicTypeGenerator.GetTypeForInterface(arg.DestinationType, arg.Settings.Includes.Count > 0, arg.Settings.Ignore);
if (destType == null)
return base.CreateInstantiationExpression(source, destination, arg);
var ctor = destType.GetConstructors()[0];
Expand Down
39 changes: 36 additions & 3 deletions src/Mapster/Utils/DynamicTypeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ internal static class DynamicTypeGenerator
private static readonly ConcurrentDictionary<Type, Type> _generated = new ConcurrentDictionary<Type, Type>();
private static int _generatedCounter;

private static IgnoreDictionary ignoreMembers;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be nullable?


public static Type? GetTypeForInterface(Type interfaceType, bool ignoreError, IgnoreDictionary ignorMembers)
{
ignoreMembers = ignorMembers;

return GetTypeForInterface(interfaceType, ignoreError);

}

public static Type? GetTypeForInterface(Type interfaceType, bool ignoreError)
{
try
Expand Down Expand Up @@ -86,13 +96,14 @@ private static Type CreateTypeForInterface(Type interfaceType)

if (hasReadonlyProps)
{
var filterargs = DropIgnorMemebers(args);
var ctorBuilder = builder.DefineConstructor(MethodAttributes.Public,
CallingConventions.Standard,
args.Select(it => it.FieldType).ToArray());
filterargs.Select(it => it.FieldType).ToArray());
var ctorIl = ctorBuilder.GetILGenerator();
for (var i = 0; i < args.Count; i++)
for (var i = 0; i < filterargs.Count; i++)
{
var arg = args[i];
var arg = filterargs[i];
ctorBuilder.DefineParameter(i + 1, ParameterAttributes.None, arg.Name.Substring(1));
ctorIl.Emit(OpCodes.Ldarg_0);
ctorIl.Emit(OpCodes.Ldarg_S, i + 1);
Expand Down Expand Up @@ -175,5 +186,27 @@ private static void CreateMethod(TypeBuilder builder, MethodInfo interfaceMethod

builder.DefineMethodOverride(classMethod, interfaceMethod);
}

private static List<FieldBuilder> DropIgnorMemebers(List<FieldBuilder> fields)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

possibly a typo: DropIgnoredMembers

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes of course. This is not the final solution, you could say MVP :)

{
var ignorFields = ignoreMembers.Select(x => x.Key).ToArray();
List<FieldBuilder> filtered = new List<FieldBuilder>();

if (ignorFields.Length == 0)
return fields;

foreach (var item in fields)
{
foreach (var check in ignorFields)
{
if (item.Name != $"_{MapsterHelper.CamelCase(check)}")
{
filtered.Add(item);
}
}
}

return filtered;
}
}
}
Loading