Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for init config from assembly by typed class configuration #10

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
13 changes: 13 additions & 0 deletions src/SimplePatch.Tests/ConfigurationTests/Globals.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ public void IgnoreLetterCase()
Assert.AreEqual(23, John.Age);
}

[TestMethod]
public void ConfigFromAssembly()
{

var assembly = typeof(Person).Assembly;
DeltaConfig.InitFromAssembly(cfg => {
cfg.AddAssembly(assembly);
});
CreateDelta<Person>("Age", 23).Patch(John);
Assert.AreEqual(23, John.Age);

}

[TestMethod]
public void MappingFunction()
{
Expand Down
33 changes: 33 additions & 0 deletions src/SimplePatch.Tests/ConfigurationTests/Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,39 @@ public void Exclude()
Assert.AreEqual(initialAge, John.Age);
}

[TestMethod]
public void ExcludedByAttribute()
{
DeltaConfig.Init(cfg =>
{
cfg
.AddEntity<Person>();
});

var initialAge = John.AgeExcludeByAttibute;

CreateDelta<Person, int>(x => x.AgeExcludeByAttibute, 23).Patch(John);

Assert.AreEqual(initialAge, John.AgeExcludeByAttibute);
}

[TestMethod]
public void ExcludedByMapping()
{
var assembly = typeof(Person).Assembly;
DeltaConfig.InitFromAssembly(cfg =>
{
cfg
.AddAssembly(assembly);
});

var initialAge = John.AgeExcludeByAttibute;

CreateDelta<Person, int>(x => x.AgeExcludeByMapping, 23).Patch(John);

Assert.AreEqual(initialAge, John.AgeExcludeByAttibute);
}

[TestMethod]
public void IgnoreNullValue()
{
Expand Down
13 changes: 13 additions & 0 deletions src/SimplePatch.Tests/Person.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using SimplePatch.Attributes;

namespace SimplePatch.Tests
{
Expand All @@ -7,6 +8,9 @@ internal class Person
public string Name { get; set; }
public string Surname { get; set; }
public int Age { get; set; }
[Exclude]
public int AgeExcludeByAttibute { get; set; }
public int AgeExcludeByMapping { get; set; }
public double Height { get; set; }
public Guid Guid { get; set; }
public DateTime BirthDate { get; set; }
Expand All @@ -23,4 +27,13 @@ internal enum Cool
{
Awesome, NotReally
}

internal class PersonConfiguration : Mapping.IEntityTypeConfiguration<Person>
{
public void Configuration(DeltaConfig.EntityConfig<Person> entityConfig)
{
entityConfig.Property(x => x.AgeExcludeByMapping).Exclude();
}
}

}
1 change: 1 addition & 0 deletions src/SimplePatch.Tests/TestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public void TestInit()
Name = "John",
Surname = "Doe",
Age = 22,
AgeExcludeByAttibute = 22,
Height = 1.7,
BirthDate = new DateTime(1990, 2, 1, 20, 15, 10)
};
Expand Down
12 changes: 12 additions & 0 deletions src/SimplePatch/Attributes/ExcludeAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SimplePatch.Attributes
{
public class ExcludeAttribute : Attribute
{
}
}
9 changes: 7 additions & 2 deletions src/SimplePatch/Delta.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using SimplePatch.Helpers;
using SimplePatch.Attributes;
using SimplePatch.Helpers;
using SimplePatch.Mapping;
using System;
using System.Collections;
Expand Down Expand Up @@ -194,7 +195,7 @@ private TEntity SetPropertiesValue(TEntity entity)
foreach (var prop in entityProperties)
{
var propertyInfo = prop.PropertyInfo;
if (ContainsKey(propertyInfo.Name) && !prop.Excluded)
if (ContainsKey(propertyInfo.Name) && !prop.Excluded && !ExcludedByAttribute(propertyInfo))
{
var truePropertyType = TypeHelper.GetTrueType(propertyInfo.PropertyType);
var newPropertyValue = this[propertyInfo.Name];
Expand Down Expand Up @@ -340,6 +341,10 @@ public bool ContainsKey(string key)
{
return dict.ContainsKey(key);
}
public bool ExcludedByAttribute(PropertyInfo propertyInfo)
{
return propertyInfo.GetCustomAttribute(typeof(ExcludeAttribute)) != null;
}

public bool Remove(string key)
{
Expand Down
133 changes: 86 additions & 47 deletions src/SimplePatch/DeltaConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
using SimplePatch.Mapping;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace SimplePatch
{
Expand All @@ -20,69 +22,74 @@ public static void Init(Action<Config> config)
config(new Config());
}

public static void InitFromAssembly(Action<ConfigFromAssembly> config) {
config(new ConfigFromAssembly());
}

internal static void Clean()
{
IgnoreLetterCase = false;
GlobalMappings?.Clear();
DeltaCache.Clear();
}

public sealed class Config
public sealed class EntityConfig<T> where T : class, new()
{
public sealed class EntityConfig<T> where T : class, new()
public PropertyConfig<T, TProp> Property<TProp>(Expression<Func<T, TProp>> property)
{
public PropertyConfig<T, TProp> Property<TProp>(Expression<Func<T, TProp>> property)
{
return new PropertyConfig<T, TProp>(property);
}
return new PropertyConfig<T, TProp>(property);
}
}

public sealed class PropertyConfig<TEntity, TProp> where TEntity : class, new()
{
private readonly string propertyName;
private readonly DeltaCache.PropertyEditor<TEntity, TProp> deltaCachePropertyEditor;
public sealed class PropertyConfig<TEntity, TProp> where TEntity : class, new()
{
private readonly string propertyName;
private readonly DeltaCache.PropertyEditor<TEntity, TProp> deltaCachePropertyEditor;

public PropertyConfig(Expression<Func<TEntity, TProp>> property)
{
propertyName = ExpressionHelper.GetPropertyName(property);
deltaCachePropertyEditor = new DeltaCache.PropertyEditor<TEntity, TProp>(propertyName);
}
public PropertyConfig(Expression<Func<TEntity, TProp>> property)
{
propertyName = ExpressionHelper.GetPropertyName(property);
deltaCachePropertyEditor = new DeltaCache.PropertyEditor<TEntity, TProp>(propertyName);
}

/// <summary>
/// Adds a mapping function for the specified property of the specified entity.
/// </summary>
/// <typeparam name="TProp">Type of the property</typeparam>
/// <param name="property">Expression which indicates the property</param>
/// <param name="mapFunction">Mapping function used to evaluate the value to be assigned to the property</param>
/// <returns></returns>
public PropertyConfig<TEntity, TProp> AddMapping(MapDelegate<TProp> mapFunction)
{
deltaCachePropertyEditor.AddMapping(mapFunction);
return this;
}
/// <summary>
/// Adds a mapping function for the specified property of the specified entity.
/// </summary>
/// <typeparam name="TProp">Type of the property</typeparam>
/// <param name="property">Expression which indicates the property</param>
/// <param name="mapFunction">Mapping function used to evaluate the value to be assigned to the property</param>
/// <returns></returns>
public PropertyConfig<TEntity, TProp> AddMapping(MapDelegate<TProp> mapFunction)
{
deltaCachePropertyEditor.AddMapping(mapFunction);
return this;
}

/// <summary>
/// Ignore null value for the specified property
/// </summary>
/// <returns></returns>
public PropertyConfig<TEntity, TProp> IgnoreNull()
{
deltaCachePropertyEditor.IgnoreNullValue();
return this;
}
/// <summary>
/// Ignore null value for the specified property
/// </summary>
/// <returns></returns>
public PropertyConfig<TEntity, TProp> IgnoreNull()
{
deltaCachePropertyEditor.IgnoreNullValue();
return this;
}

/// <summary>
/// Marks the specified property as excluded when calling <see cref="Delta{TEntity}.Patch(TEntity)"/>.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="properties"></param>
/// <returns></returns>
public PropertyConfig<TEntity, TProp> Exclude()
{
deltaCachePropertyEditor.Exclude();
return this;
}
/// <summary>
/// Marks the specified property as excluded when calling <see cref="Delta{TEntity}.Patch(TEntity)"/>.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="properties"></param>
/// <returns></returns>
public PropertyConfig<TEntity, TProp> Exclude()
{
deltaCachePropertyEditor.Exclude();
return this;
}
}

public sealed class Config
{

/// <summary>
/// Allows to add settings for the specified property
Expand Down Expand Up @@ -119,5 +126,37 @@ public Config AddMapping(MapDelegate<object> mappingFunc)
return this;
}
}

public sealed class ConfigFromAssembly
{
private Config config;
public ConfigFromAssembly() {
this.config = new Config();
}
public ConfigFromAssembly AddAssembly(Assembly assembly) {

var types = assembly.GetTypes();
foreach (var type in types)
{
var interfaces = type.GetInterfaces();
var implementedInterface = interfaces.Where(x => x.IsConstructedGenericType && x.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>)).FirstOrDefault();
if (implementedInterface != null) {
//add entity
var methodDef = typeof(Config).GetMethod("AddEntity");
var method = methodDef.MakeGenericMethod(new Type[] { implementedInterface.GetGenericArguments()[0] });
var entityConfig = method.Invoke(config, new object[] { });
//run config from entity
var obj = Activator.CreateInstance(type);
var configurationMethodDef = type.GetMethod("Configuration");
configurationMethodDef.Invoke(obj, new object[] { entityConfig });

}
}
return this;
}
}



}
}
13 changes: 13 additions & 0 deletions src/SimplePatch/Mapping/IEntityTypeConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SimplePatch.Mapping
{
public interface IEntityTypeConfiguration<TEntity> where TEntity : class, new()
{
void Configuration(DeltaConfig.EntityConfig<TEntity> entityConfig);
}
}
4 changes: 4 additions & 0 deletions src/SimplePatch/SimplePatch.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,8 @@
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.5.1" />
</ItemGroup>

<ItemGroup>
<Folder Include="Attributes\" />
</ItemGroup>

</Project>