Created
March 15, 2013 13:30
-
-
Save jogibear9988/5169867 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Source/BLToolkit.4.csproj | 2 + | |
Source/Mapping/Fluent/AssociationMap.cs | 58 ++++++++++++++++++++-- | |
Source/Mapping/Fluent/Attributes.cs | 15 ++++++ | |
Source/Mapping/Fluent/FluentMap.Interface.cs | 23 ++++++++- | |
Source/Mapping/Fluent/FluentMap.cs | 14 ++++-- | |
Source/Mapping/Fluent/IFluentMap.cs | 4 +- | |
Source/Mapping/Fluent/MapFieldMap.cs | 12 +++-- | |
Source/Mapping/ObjectMapper.cs | 19 +++++++ | |
Source/Reflection/Extension/TypeExtension.cs | 3 +- | |
.../MetadataProvider/AttributeMetadataProvider.cs | 22 ++++++++ | |
.../MetadataProvider/ExtensionMetadataProvider.cs | 30 +++++++++++ | |
.../MetadataProvider/LinqMetadataProvider.cs | 2 +- | |
.../MetadataProvider/MetadataProviderBase.cs | 9 ++++ | |
.../MetadataProvider/MetadataProviderList.cs | 17 +++++++ | |
UnitTests/Fluent/UnitTests.Fluent.csproj | 1 + | |
15 files changed, 216 insertions(+), 15 deletions(-) | |
diff --git a/Source/BLToolkit.4.csproj b/Source/BLToolkit.4.csproj | |
index 4fe53c7..5b2accd 100644 | |
--- a/Source/BLToolkit.4.csproj | |
+++ b/Source/BLToolkit.4.csproj | |
@@ -341,6 +341,8 @@ | |
<Compile Include="Data\Sql\SqlValue.cs" /> | |
<Compile Include="Mapping\AssociationAttribute.cs" /> | |
<Compile Include="Mapping\Association.cs" /> | |
+ <Compile Include="Mapping\ManyToManyAssociation.cs" /> | |
+ <Compile Include="Mapping\ManyToManyAssociationAttribute.cs" /> | |
<Compile Include="Mapping\ExpressionMapper.cs" /> | |
<Compile Include="Mapping\Fluent\AssociationMap.cs" /> | |
<Compile Include="Mapping\Fluent\Attributes.cs" /> | |
diff --git a/Source/Mapping/Fluent/AssociationMap.cs b/Source/Mapping/Fluent/AssociationMap.cs | |
index edfbb06..00f9aa9 100644 | |
--- a/Source/Mapping/Fluent/AssociationMap.cs | |
+++ b/Source/Mapping/Fluent/AssociationMap.cs | |
@@ -1,6 +1,8 @@ | |
using System; | |
using System.Collections.Generic; | |
using System.Linq.Expressions; | |
+using System.Linq; | |
+ | |
namespace BLToolkit.Mapping.Fluent | |
{ | |
@@ -24,14 +26,60 @@ namespace BLToolkit.Mapping.Fluent | |
var keys = new List<Expression<Func<TRf, TRo>>>(otherKeys); | |
keys.Insert(0, otherKey); | |
return this._owner.Association(this._canBeNull, this._thisKeys, keys); | |
- } | |
- | |
- public MapFieldMap<T, TR> ToOne<TRo>(Expression<Func<TR, TRo>> otherKey, params Expression<Func<TR, TRo>>[] otherKeys) | |
+ } | |
+ | |
+ public MapFieldMap<T, TR> ToOne<TRo>(Expression<Func<TR, TRo>> otherKey, params Expression<Func<TR, TRo>>[] otherKeys) | |
{ | |
var keys = new List<Expression<Func<TR, TRo>>>(otherKeys); | |
keys.Insert(0, otherKey); | |
return this._owner.Association(this._canBeNull, this._thisKeys, keys); | |
- } | |
- } | |
+ } | |
+ | |
+ | |
+ #region ManyToMany Relations | |
+ | |
+ public MapFieldMap<T, TR> ToManyRel<TRf, TRo>(Expression<Func<TRf, TRo>> otherKey) | |
+ { | |
+ return ToManyRel(otherKey); | |
+ } | |
+ | |
+ public MapFieldMap<T, TR> ToManyRel<TRf, TRo, TRmap, TRthis, TRother>(Expression<Func<TRf, TRo>> otherKey, Expression<Func<TRmap, TRthis>> relThisKey, Expression<Func<TRmap, TRother>> relOtherKey) | |
+ { | |
+ return ToManyRel(otherKey, KeysToString(new[] { relThisKey }), KeysToString(new[] { relOtherKey })); | |
+ } | |
+ | |
+ public MapFieldMap<T, TR> ToManyRel<TRf, TRo>(Expression<Func<TRf, TRo>> otherKey, string relThisKey = null, string relOtherKey = null, string relTable = null) | |
+ { | |
+ var keys = new List<Expression<Func<TRf, TRo>>>(); | |
+ keys.Insert(0, otherKey); | |
+ return this._owner.ManyToManyAssociation(this._canBeNull, this._thisKeys, keys, relThisKey, relOtherKey, relTable); | |
+ } | |
+ | |
+ #endregion | |
+ | |
+ private const string MemberNameSeparator = "."; | |
+ | |
+ private string GetExprName<TT, TR>(Expression<Func<TT, TR>> prop) | |
+ { | |
+ string result = null; | |
+ var memberExpression = prop.Body as MemberExpression; | |
+ while (null != memberExpression) | |
+ { | |
+ result = null == result ? "" : MemberNameSeparator + result; | |
+ result = memberExpression.Member.Name + result; | |
+ memberExpression = memberExpression.Expression as MemberExpression; | |
+ } | |
+ if (null == result) | |
+ { | |
+ throw new ArgumentException("Fail member access expression."); | |
+ } | |
+ return result; | |
+ } | |
+ | |
+ private string KeysToString<T1, T2>(IEnumerable<Expression<Func<T1, T2>>> keys) | |
+ { | |
+ return keys.Select(this.GetExprName).Aggregate((s1, s2) => s1 + ", " + s2); | |
+ } | |
+ } | |
} | |
} | |
\ No newline at end of file | |
diff --git a/Source/Mapping/Fluent/Attributes.cs b/Source/Mapping/Fluent/Attributes.cs | |
index ab4fc32..571b72e 100644 | |
--- a/Source/Mapping/Fluent/Attributes.cs | |
+++ b/Source/Mapping/Fluent/Attributes.cs | |
@@ -77,6 +77,21 @@ | |
public const string Storage = "Storage"; | |
} | |
+ public static class ManyToManyAssociation | |
+ { | |
+ public const string ThisKey = "ThisKey"; | |
+ | |
+ public const string OtherKey = "OtherKey"; | |
+ | |
+ public const string Storage = "Storage"; | |
+ | |
+ public const string RelationTableThisKey = "RelationTableThisKey"; | |
+ | |
+ public const string RelationTableOtherKey = "RelationTableOtherKey"; | |
+ | |
+ public const string RelationTableName = "RelationTableName"; | |
+ } | |
+ | |
public const string NonUpdatable = "NonUpdatable"; | |
public const string Identity = "Identity"; | |
diff --git a/Source/Mapping/Fluent/FluentMap.Interface.cs b/Source/Mapping/Fluent/FluentMap.Interface.cs | |
index 61ecd6c..6f64617 100644 | |
--- a/Source/Mapping/Fluent/FluentMap.Interface.cs | |
+++ b/Source/Mapping/Fluent/FluentMap.Interface.cs | |
@@ -278,7 +278,28 @@ namespace BLToolkit.Mapping.Fluent | |
attributeExtension.Values.Add(Attributes.Association.Storage, this.ToString(canBeNull)); | |
attrs.Add(attributeExtension); | |
this.EachChilds(m => m.Association(propName, canBeNull, thisKeys, otherKeys)); | |
- } | |
+ } | |
+ | |
+ void IFluentMap.ManyToManyAssociation(string propName, bool canBeNull, string thisKeys, string otherKeys, string thisKeysRel, string otherKeysRel, string relTableName) | |
+ { | |
+ var member = this.GetMemberExtension(propName); | |
+ AttributeExtensionCollection attrs; | |
+ if (!member.Attributes.TryGetValue(TypeExtension.NodeName.ManyToManyAssociation, out attrs)) | |
+ { | |
+ attrs = new AttributeExtensionCollection(); | |
+ member.Attributes.Add(TypeExtension.NodeName.ManyToManyAssociation, attrs); | |
+ } | |
+ attrs.Clear(); | |
+ var attributeExtension = new AttributeExtension(); | |
+ attributeExtension.Values.Add(Attributes.ManyToManyAssociation.ThisKey, thisKeys); | |
+ attributeExtension.Values.Add(Attributes.ManyToManyAssociation.OtherKey, otherKeys); | |
+ attributeExtension.Values.Add(Attributes.ManyToManyAssociation.Storage, this.ToString(canBeNull)); | |
+ attributeExtension.Values.Add(Attributes.ManyToManyAssociation.RelationTableThisKey, thisKeysRel); | |
+ attributeExtension.Values.Add(Attributes.ManyToManyAssociation.RelationTableOtherKey, thisKeysRel); | |
+ attributeExtension.Values.Add(Attributes.ManyToManyAssociation.RelationTableName, relTableName); | |
+ attrs.Add(attributeExtension); | |
+ this.EachChilds(m => m.Association(propName, canBeNull, thisKeys, otherKeys)); | |
+ } | |
/// <summary> | |
/// Relations the specified prop name. | |
diff --git a/Source/Mapping/Fluent/FluentMap.cs b/Source/Mapping/Fluent/FluentMap.cs | |
index 7308d2b..36d2361 100644 | |
--- a/Source/Mapping/Fluent/FluentMap.cs | |
+++ b/Source/Mapping/Fluent/FluentMap.cs | |
@@ -343,9 +343,17 @@ namespace BLToolkit.Mapping.Fluent | |
string name = this.GetExprName(prop); | |
((IFluentMap)this).Association(name, canBeNull, this.KeysToString(thisKeys.ToArray()), this.KeysToString(otherKeys.ToArray())); | |
return new MapFieldMap<T, TR>(this._typeExtension, this.Childs, prop); | |
- } | |
- | |
- /// <summary> | |
+ } | |
+ | |
+ protected MapFieldMap<T, TR> ManyToManyAssociation<TRt, TR, TRf, TRo>(Expression<Func<T, TR>> prop, bool canBeNull | |
+ , IEnumerable<Expression<Func<T, TRt>>> thisKeys, IEnumerable<Expression<Func<TRf, TRo>>> otherKeys, string relThisKey, string relOtherKey, string relTable) | |
+ { | |
+ string name = this.GetExprName(prop); | |
+ ((IFluentMap)this).ManyToManyAssociation(name, canBeNull, this.KeysToString(thisKeys.ToArray()), this.KeysToString(otherKeys.ToArray()), relThisKey, relOtherKey, relTable); | |
+ return new MapFieldMap<T, TR>(this._typeExtension, this.Childs, prop); | |
+ } | |
+ | |
+ /// <summary> | |
/// Reverse on BLToolkit.Mapping.Association.ParseKeys() | |
/// </summary> | |
/// <typeparam name="T1"></typeparam> | |
diff --git a/Source/Mapping/Fluent/IFluentMap.cs b/Source/Mapping/Fluent/IFluentMap.cs | |
index b3d2ba8..f5a4076 100644 | |
--- a/Source/Mapping/Fluent/IFluentMap.cs | |
+++ b/Source/Mapping/Fluent/IFluentMap.cs | |
@@ -155,7 +155,9 @@ namespace BLToolkit.Mapping.Fluent | |
/// <param name="canBeNull">if set to <c>true</c> [can be null].</param> | |
/// <param name="thisKeys">The this keys.</param> | |
/// <param name="otherKeys">The other keys.</param> | |
- void Association(string propName, bool canBeNull, string thisKeys, string otherKeys); | |
+ void Association(string propName, bool canBeNull, string thisKeys, string otherKeys); | |
+ | |
+ void ManyToManyAssociation(string propName, bool canBeNull, string thisKeys, string otherKeys, string thisKeysRel, string otherKeysRel, string relTable); | |
/// <summary> | |
/// Relations the specified prop name. | |
diff --git a/Source/Mapping/Fluent/MapFieldMap.cs b/Source/Mapping/Fluent/MapFieldMap.cs | |
index 577734c..0fc6f33 100644 | |
--- a/Source/Mapping/Fluent/MapFieldMap.cs | |
+++ b/Source/Mapping/Fluent/MapFieldMap.cs | |
@@ -185,9 +185,15 @@ namespace BLToolkit.Mapping.Fluent | |
, IEnumerable<Expression<Func<T, TRt>>> thisKeys, IEnumerable<Expression<Func<TRf, TRo>>> otherKeys) | |
{ | |
return this.Association(this._prop, canBeNull, thisKeys, otherKeys); | |
- } | |
- | |
- /// <summary> | |
+ } | |
+ | |
+ private MapFieldMap<T, TR> ManyToManyAssociation<TRt, TRf, TRo>(bool canBeNull | |
+ , IEnumerable<Expression<Func<T, TRt>>> thisKeys, IEnumerable<Expression<Func<TRf, TRo>>> otherKeys, string relThisKey, string relOtherKey, string relTable) | |
+ { | |
+ return this.ManyToManyAssociation(this._prop, canBeNull, thisKeys, otherKeys, relThisKey, relOtherKey, relTable); | |
+ } | |
+ | |
+ /// <summary> | |
/// RelationAttribute | |
/// </summary> | |
/// <param name="slaveIndex"></param> | |
diff --git a/Source/Mapping/ObjectMapper.cs b/Source/Mapping/ObjectMapper.cs | |
index 97549a1..1ace202 100644 | |
--- a/Source/Mapping/ObjectMapper.cs | |
+++ b/Source/Mapping/ObjectMapper.cs | |
@@ -112,6 +112,12 @@ namespace BLToolkit.Mapping | |
get { return _associations; } | |
} | |
+ readonly List<ManyToManyAssociation> _manyToManyAssociations = new List<ManyToManyAssociation>(); | |
+ public List<ManyToManyAssociation> ManyToManyAssociations | |
+ { | |
+ get { return _manyToManyAssociations; } | |
+ } | |
+ | |
readonly List<InheritanceMappingAttribute> _inheritanceMapping = new List<InheritanceMappingAttribute>(); | |
public List<InheritanceMappingAttribute> InheritanceMapping | |
{ | |
@@ -259,6 +265,14 @@ namespace BLToolkit.Mapping | |
continue; | |
} | |
+ var b = this.GetManyToManyAssociation(ma); | |
+ | |
+ if (b != null) | |
+ { | |
+ _manyToManyAssociations.Add(b); | |
+ continue; | |
+ } | |
+ | |
if (GetMapIgnore(ma)) | |
continue; | |
@@ -564,6 +578,11 @@ namespace BLToolkit.Mapping | |
return MetadataProvider.GetAssociation(Extension, memberAccessor); | |
} | |
+ protected virtual ManyToManyAssociation GetManyToManyAssociation(MemberAccessor memberAccessor) | |
+ { | |
+ return MetadataProvider.GetManyToManyAssociation(Extension, memberAccessor); | |
+ } | |
+ | |
protected virtual InheritanceMappingAttribute[] GetInheritanceMapping() | |
{ | |
return MetadataProvider.GetInheritanceMapping(_typeAccessor.OriginalType, Extension); | |
diff --git a/Source/Reflection/Extension/TypeExtension.cs b/Source/Reflection/Extension/TypeExtension.cs | |
index ed5c4d2..fdc3864 100644 | |
--- a/Source/Reflection/Extension/TypeExtension.cs | |
+++ b/Source/Reflection/Extension/TypeExtension.cs | |
@@ -16,7 +16,8 @@ namespace BLToolkit.Reflection.Extension | |
public const string Type = "Type"; | |
public const string Member = "Member"; | |
public const string Association = "Association"; | |
- public const string Relation = "Relation"; | |
+ public const string ManyToManyAssociation = "ManyToManyAssociation"; | |
+ public const string Relation = "Relation"; | |
public const string MasterIndex = "MasterIndex"; | |
public const string SlaveIndex = "SlaveIndex"; | |
} | |
diff --git a/Source/Reflection/MetadataProvider/AttributeMetadataProvider.cs b/Source/Reflection/MetadataProvider/AttributeMetadataProvider.cs | |
index b55e9b4..96787e4 100644 | |
--- a/Source/Reflection/MetadataProvider/AttributeMetadataProvider.cs | |
+++ b/Source/Reflection/MetadataProvider/AttributeMetadataProvider.cs | |
@@ -682,6 +682,28 @@ namespace BLToolkit.Reflection.MetadataProvider | |
#endregion | |
+ #region GetManyToManyAssociation | |
+ | |
+ public override ManyToManyAssociation GetManyToManyAssociation(TypeExtension typeExtension, MemberAccessor member) | |
+ { | |
+ var aa = member.GetAttribute<ManyToManyAssociationAttribute>(); | |
+ | |
+ if (aa == null) | |
+ return base.GetManyToManyAssociation(typeExtension, member); | |
+ | |
+ return new ManyToManyAssociation( | |
+ member, | |
+ aa.GetThisKeys(), | |
+ aa.GetOtherKeys(), | |
+ aa.Storage, | |
+ aa.CanBeNull, | |
+ aa.GetRelationTableThisKeys(), | |
+ aa.GetRelationTableOtherKeys(), | |
+ aa.RelationTableName); | |
+ } | |
+ | |
+ #endregion | |
+ | |
#region GetInheritanceMapping | |
public override InheritanceMappingAttribute[] GetInheritanceMapping(Type type, TypeExtension typeExtension) | |
diff --git a/Source/Reflection/MetadataProvider/ExtensionMetadataProvider.cs b/Source/Reflection/MetadataProvider/ExtensionMetadataProvider.cs | |
index f9f93a9..2d2b439 100644 | |
--- a/Source/Reflection/MetadataProvider/ExtensionMetadataProvider.cs | |
+++ b/Source/Reflection/MetadataProvider/ExtensionMetadataProvider.cs | |
@@ -511,6 +511,36 @@ namespace BLToolkit.Reflection.MetadataProvider | |
#endregion | |
+ #region GetManyToManyAssociation | |
+ | |
+ public override ManyToManyAssociation GetManyToManyAssociation(TypeExtension typeExtension, MemberAccessor member) | |
+ { | |
+ if (typeExtension == TypeExtension.Null) | |
+ return null; | |
+ | |
+ var mex = typeExtension[member.Name]; | |
+ | |
+ if (mex == MemberExtension.Null) | |
+ return null; | |
+ | |
+ var attrs = mex.Attributes[TypeExtension.NodeName.Association]; | |
+ | |
+ if (attrs == AttributeExtensionCollection.Null) | |
+ return null; | |
+ | |
+ return new ManyToManyAssociation( | |
+ member, | |
+ Association.ParseKeys(attrs[0]["ThisKey", string.Empty].ToString()), | |
+ Association.ParseKeys(attrs[0]["OtherKey", string.Empty].ToString()), | |
+ attrs[0]["Storage", string.Empty].ToString(), | |
+ TypeExtension.ToBoolean(attrs[0]["Storage", "True"], true), | |
+ Association.ParseKeys(attrs[0]["RelThisKey", string.Empty].ToString()), | |
+ Association.ParseKeys(attrs[0]["RelOtherKey", string.Empty].ToString()), | |
+ attrs[0]["RelTableName", string.Empty].ToString()); | |
+ } | |
+ | |
+ #endregion | |
+ | |
#region GetInheritanceMapping | |
public override InheritanceMappingAttribute[] GetInheritanceMapping(Type type, TypeExtension typeExtension) | |
diff --git a/Source/Reflection/MetadataProvider/LinqMetadataProvider.cs b/Source/Reflection/MetadataProvider/LinqMetadataProvider.cs | |
index 2fc3bb3..210130f 100644 | |
--- a/Source/Reflection/MetadataProvider/LinqMetadataProvider.cs | |
+++ b/Source/Reflection/MetadataProvider/LinqMetadataProvider.cs | |
@@ -219,7 +219,7 @@ namespace BLToolkit.Reflection.MetadataProvider | |
#endregion | |
- #region GetInheritanceMapping | |
+ #region GetInheritanceMapping | |
public override InheritanceMappingAttribute[] GetInheritanceMapping(Type type,TypeExtension typeExtension) | |
{ | |
diff --git a/Source/Reflection/MetadataProvider/MetadataProviderBase.cs b/Source/Reflection/MetadataProvider/MetadataProviderBase.cs | |
index d27d66a..06384c4 100644 | |
--- a/Source/Reflection/MetadataProvider/MetadataProviderBase.cs | |
+++ b/Source/Reflection/MetadataProvider/MetadataProviderBase.cs | |
@@ -267,6 +267,15 @@ namespace BLToolkit.Reflection.MetadataProvider | |
#endregion | |
+ #region GetManyToManyAssociation | |
+ | |
+ public virtual ManyToManyAssociation GetManyToManyAssociation(TypeExtension typeExtension, MemberAccessor member) | |
+ { | |
+ return null; | |
+ } | |
+ | |
+ #endregion | |
+ | |
#region GetInheritanceMapping | |
public virtual InheritanceMappingAttribute[] GetInheritanceMapping(Type type, TypeExtension typeExtension) | |
diff --git a/Source/Reflection/MetadataProvider/MetadataProviderList.cs b/Source/Reflection/MetadataProvider/MetadataProviderList.cs | |
index c6d4f76..9184337 100644 | |
--- a/Source/Reflection/MetadataProvider/MetadataProviderList.cs | |
+++ b/Source/Reflection/MetadataProvider/MetadataProviderList.cs | |
@@ -371,6 +371,23 @@ namespace BLToolkit.Reflection.MetadataProvider | |
#endregion | |
+ #region GetAssociation | |
+ | |
+ public override ManyToManyAssociation GetManyToManyAssociation(TypeExtension typeExtension, MemberAccessor member) | |
+ { | |
+ foreach (var p in _list) | |
+ { | |
+ var attr = p.GetManyToManyAssociation(typeExtension, member); | |
+ | |
+ if (attr != null) | |
+ return attr; | |
+ } | |
+ | |
+ return base.GetManyToManyAssociation(typeExtension, member); | |
+ } | |
+ | |
+ #endregion | |
+ | |
#region GetInheritanceMapping | |
public override InheritanceMappingAttribute[] GetInheritanceMapping(Type type, TypeExtension typeExtension) | |
diff --git a/UnitTests/Fluent/UnitTests.Fluent.csproj b/UnitTests/Fluent/UnitTests.Fluent.csproj | |
index edd72c6..6aaf486 100644 | |
--- a/UnitTests/Fluent/UnitTests.Fluent.csproj | |
+++ b/UnitTests/Fluent/UnitTests.Fluent.csproj | |
@@ -49,6 +49,7 @@ | |
<ItemGroup> | |
<Compile Include="AssertExceptionEx.cs" /> | |
<Compile Include="FluentMapAttributesTest.cs" /> | |
+ <Compile Include="FluentMapManyToManyTest.cs" /> | |
<Compile Include="FluentConfigTest.cs" /> | |
<Compile Include="FluentMapTest.cs" /> | |
<Compile Include="MockDataBase\AssertCommandData.cs" /> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment